2005-01-06 01:43:34 +00:00
/*-
2017-11-27 14:52:40 +00:00
* SPDX - License - Identifier : BSD - 2 - Clause - FreeBSD
*
2020-11-20 01:15:48 +00:00
* Copyright ( c ) 2009 - 2020 Alexander Motin < mav @ FreeBSD . org >
2009-08-01 01:04:26 +00:00
* Copyright ( c ) 1997 - 2009 by Matthew Jacob
2007-03-10 02:39:54 +00:00
* All rights reserved .
2009-08-01 01:04:26 +00:00
*
2007-03-10 02:39:54 +00:00
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
2009-08-01 01:04:26 +00:00
*
2007-03-10 02:39:54 +00:00
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
2009-08-01 01:04:26 +00:00
*
2007-03-10 02:39:54 +00:00
* THIS SOFTWARE IS PROVIDED BY 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 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 .
2009-08-01 01:04:26 +00:00
*
1998-04-22 17:54:58 +00:00
*/
2006-07-16 20:11:50 +00:00
/*
* Machine and OS Independent ( well , as best as possible )
2006-11-16 00:31:46 +00:00
* code for the Qlogic ISP SCSI and FC - SCSI adapters .
2006-07-16 20:11:50 +00:00
*/
2006-11-16 00:31:46 +00:00
1998-04-22 17:54:58 +00:00
/*
* Inspiration and ideas about this driver are from Erik Moe ' s Linux driver
* ( qlogicisp . c ) and Dave Miller ' s SBus version of same ( qlogicisp . c ) . Some
* ideas dredged from the Solaris driver .
*/
/*
* Include header file appropriate for platform we ' re building on .
*/
# ifdef __NetBSD__
2007-03-10 02:39:54 +00:00
# include <sys/cdefs.h>
__KERNEL_RCSID ( 0 , " $NetBSD$ " ) ;
1998-04-22 17:54:58 +00:00
# include <dev/ic/isp_netbsd.h>
# endif
# ifdef __FreeBSD__
2006-07-16 20:11:50 +00:00
# include <sys/cdefs.h>
__FBSDID ( " $FreeBSD$ " ) ;
1998-04-22 17:54:58 +00:00
# include <dev/isp/isp_freebsd.h>
# endif
1999-03-17 05:04:39 +00:00
# ifdef __OpenBSD__
# include <dev/ic/isp_openbsd.h>
# endif
1998-04-22 17:54:58 +00:00
# ifdef __linux__
1998-12-28 19:22:27 +00:00
# include "isp_linux.h"
1998-04-22 17:54:58 +00:00
# endif
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
# ifdef __svr4__
# include "isp_solaris.h"
# endif
1998-04-22 17:54:58 +00:00
/*
1998-09-15 08:42:56 +00:00
* Local static data
1998-04-22 17:54:58 +00:00
*/
2017-03-22 08:56:03 +00:00
static const char notresp [ ] = " Unknown IOCB in RESPONSE Queue (type 0x%x) @ idx %d (next %d) " ;
2010-03-26 15:13:31 +00:00
static const char bun [ ] = " bad underrun (count %d, resid %d, status %s) " ;
2009-08-01 01:04:26 +00:00
static const char lipd [ ] = " Chan %d LIP destroyed %d active commands " ;
static const char sacq [ ] = " unable to acquire scratch area " ;
static const uint8_t alpa_map [ ] = {
0xef , 0xe8 , 0xe4 , 0xe2 , 0xe1 , 0xe0 , 0xdc , 0xda ,
0xd9 , 0xd6 , 0xd5 , 0xd4 , 0xd3 , 0xd2 , 0xd1 , 0xce ,
0xcd , 0xcc , 0xcb , 0xca , 0xc9 , 0xc7 , 0xc6 , 0xc5 ,
0xc3 , 0xbc , 0xba , 0xb9 , 0xb6 , 0xb5 , 0xb4 , 0xb3 ,
0xb2 , 0xb1 , 0xae , 0xad , 0xac , 0xab , 0xaa , 0xa9 ,
0xa7 , 0xa6 , 0xa5 , 0xa3 , 0x9f , 0x9e , 0x9d , 0x9b ,
0x98 , 0x97 , 0x90 , 0x8f , 0x88 , 0x84 , 0x82 , 0x81 ,
0x80 , 0x7c , 0x7a , 0x79 , 0x76 , 0x75 , 0x74 , 0x73 ,
0x72 , 0x71 , 0x6e , 0x6d , 0x6c , 0x6b , 0x6a , 0x69 ,
0x67 , 0x66 , 0x65 , 0x63 , 0x5c , 0x5a , 0x59 , 0x56 ,
0x55 , 0x54 , 0x53 , 0x52 , 0x51 , 0x4e , 0x4d , 0x4c ,
0x4b , 0x4a , 0x49 , 0x47 , 0x46 , 0x45 , 0x43 , 0x3c ,
0x3a , 0x39 , 0x36 , 0x35 , 0x34 , 0x33 , 0x32 , 0x31 ,
0x2e , 0x2d , 0x2c , 0x2b , 0x2a , 0x29 , 0x27 , 0x26 ,
0x25 , 0x23 , 0x1f , 0x1e , 0x1d , 0x1b , 0x18 , 0x17 ,
0x10 , 0x0f , 0x08 , 0x04 , 0x02 , 0x01 , 0x00
} ;
2001-08-20 17:28:32 +00:00
1998-09-15 08:42:56 +00:00
/*
* Local function prototypes .
*/
2020-11-27 15:50:20 +00:00
static int isp_handle_control ( ispsoftc_t * , isphdr_t * ) ;
static void isp_handle_rpt_id_acq ( ispsoftc_t * , isphdr_t * ) ;
2020-11-26 18:47:23 +00:00
static void isp_parse_status_24xx ( ispsoftc_t * , isp24xx_statusreq_t * , XS_T * ) ;
2015-11-19 17:43:47 +00:00
static void isp_clear_portdb ( ispsoftc_t * , int ) ;
static void isp_mark_portdb ( ispsoftc_t * , int ) ;
2015-12-26 06:13:01 +00:00
static int isp_plogx ( ispsoftc_t * , int , uint16_t , uint32_t , int ) ;
2015-12-27 06:28:31 +00:00
static int isp_getpdb ( ispsoftc_t * , int , uint16_t , isp_pdb_t * ) ;
static int isp_gethandles ( ispsoftc_t * , int , uint16_t * , int * , int ) ;
static void isp_dump_chip_portdb ( ispsoftc_t * , int ) ;
2009-08-01 01:04:26 +00:00
static uint64_t isp_get_wwn ( ispsoftc_t * , int , int , int ) ;
static int isp_fclink_test ( ispsoftc_t * , int , int ) ;
static int isp_pdb_sync ( ispsoftc_t * , int ) ;
static int isp_scan_loop ( ispsoftc_t * , int ) ;
2017-07-03 15:56:45 +00:00
static int isp_gid_pt ( ispsoftc_t * , int ) ;
2009-08-01 01:04:26 +00:00
static int isp_scan_fabric ( ispsoftc_t * , int ) ;
static int isp_login_device ( ispsoftc_t * , int , uint32_t , isp_pdb_t * , uint16_t * ) ;
static int isp_register_fc4_type ( ispsoftc_t * , int ) ;
2015-11-17 19:57:49 +00:00
static int isp_register_fc4_features_24xx ( ispsoftc_t * , int ) ;
2016-04-09 14:50:47 +00:00
static int isp_register_port_name_24xx ( ispsoftc_t * , int ) ;
static int isp_register_node_name_24xx ( ispsoftc_t * , int ) ;
2015-10-27 18:32:03 +00:00
static uint16_t isp_next_handle ( ispsoftc_t * , uint16_t * ) ;
2015-11-17 16:33:46 +00:00
static int isp_fw_state ( ispsoftc_t * , int ) ;
2006-11-02 03:21:32 +00:00
static void isp_mboxcmd ( ispsoftc_t * , mbreg_t * ) ;
2006-04-21 18:30:01 +00:00
2009-08-01 01:04:26 +00:00
static void isp_setdfltfcparm ( ispsoftc_t * , int ) ;
static int isp_read_nvram ( ispsoftc_t * , int ) ;
2020-11-20 01:15:48 +00:00
static int isp_read_nvram_2400 ( ispsoftc_t * ) ;
2006-11-02 03:21:32 +00:00
static void isp_rd_2400_nvram ( ispsoftc_t * , uint32_t , uint32_t * ) ;
static void isp_parse_nvram_2400 ( ispsoftc_t * , uint8_t * ) ;
2000-02-11 19:31:32 +00:00
2015-11-17 16:33:46 +00:00
static void
isp_change_fw_state ( ispsoftc_t * isp , int chan , int state )
{
fcparam * fcp = FCPARAM ( isp , chan ) ;
if ( fcp - > isp_fwstate = = state )
return ;
isp_prt ( isp , ISP_LOGCONFIG | ISP_LOG_SANCFG ,
" Chan %d Firmware state <%s->%s> " , chan ,
isp_fc_fw_statename ( fcp - > isp_fwstate ) , isp_fc_fw_statename ( state ) ) ;
fcp - > isp_fwstate = state ;
}
1998-04-22 17:54:58 +00:00
/*
* Reset Hardware .
1998-09-15 08:42:56 +00:00
*
1999-10-30 19:32:44 +00:00
* Hit the chip over the head , download new f / w if available and set it running .
1998-09-15 08:42:56 +00:00
*
* Locking done elsewhere .
1998-04-22 17:54:58 +00:00
*/
2001-08-31 21:39:04 +00:00
1998-04-22 17:54:58 +00:00
void
2009-08-01 01:04:26 +00:00
isp_reset ( ispsoftc_t * isp , int do_load_defaults )
1998-04-22 17:54:58 +00:00
{
mbreg_t mbs ;
2012-06-17 21:39:40 +00:00
char * buf ;
uint64_t fwt ;
2006-11-02 03:21:32 +00:00
uint32_t code_org , val ;
2020-11-26 18:47:23 +00:00
int loaded_fw , loops , i , dodnld = 1 ;
2009-08-01 01:04:26 +00:00
const char * btype = " ???? " ;
2006-11-02 03:21:32 +00:00
static const char dcrc [ ] = " Downloaded RISC Code Checksum Failure " ;
1998-04-22 17:54:58 +00:00
2017-03-14 08:03:56 +00:00
isp - > isp_state = ISP_NILSTATE ;
2006-11-02 03:21:32 +00:00
ISP_DISABLE_INTS ( isp ) ;
1999-01-30 07:29:00 +00:00
/*
2001-01-15 18:33:08 +00:00
* Put the board into PAUSE mode ( so we can read the SXP registers
* or write FPM / FBM registers ) .
1999-01-30 07:29:00 +00:00
*/
2020-11-20 01:15:48 +00:00
ISP_WRITE ( isp , BIU2400_HCCR , HCCR_2400_CMD_CLEAR_HOST_INT ) ;
ISP_WRITE ( isp , BIU2400_HCCR , HCCR_2400_CMD_CLEAR_RISC_INT ) ;
ISP_WRITE ( isp , BIU2400_HCCR , HCCR_2400_CMD_PAUSE ) ;
1999-01-30 07:29:00 +00:00
2020-11-20 01:15:48 +00:00
switch ( isp - > isp_type ) {
case ISP_HA_FC_2400 :
btype = " 2422 " ;
break ;
case ISP_HA_FC_2500 :
btype = " 2532 " ;
break ;
case ISP_HA_FC_2600 :
btype = " 2600 " ;
break ;
case ISP_HA_FC_2700 :
btype = " 2700 " ;
break ;
default :
break ;
1998-04-22 17:54:58 +00:00
}
2020-11-20 01:15:48 +00:00
/*
* Stop DMA and wait for it to stop .
*/
ISP_WRITE ( isp , BIU2400_CSR , BIU2400_DMA_STOP | ( 3 < < 4 ) ) ;
2020-11-26 18:47:23 +00:00
for ( loops = 0 ; loops < 100000 ; loops + + ) {
2020-11-20 01:15:48 +00:00
ISP_DELAY ( 10 ) ;
val = ISP_READ ( isp , BIU2400_CSR ) ;
if ( ( val & BIU2400_DMA_ACTIVE ) = = 0 ) {
break ;
2006-11-02 03:21:32 +00:00
}
2020-11-20 01:15:48 +00:00
}
2020-11-26 18:47:23 +00:00
if ( val & BIU2400_DMA_ACTIVE )
2020-11-20 01:15:48 +00:00
isp_prt ( isp , ISP_LOGERR , " DMA Failed to Stop on Reset " ) ;
2020-11-26 18:47:23 +00:00
2020-11-20 01:15:48 +00:00
/*
* Hold it in SOFT_RESET and STOP state for 100u s .
*/
ISP_WRITE ( isp , BIU2400_CSR , BIU2400_SOFT_RESET | BIU2400_DMA_STOP | ( 3 < < 4 ) ) ;
ISP_DELAY ( 100 ) ;
for ( loops = 0 ; loops < 10000 ; loops + + ) {
ISP_DELAY ( 5 ) ;
val = ISP_READ ( isp , OUTMAILBOX0 ) ;
2020-11-26 18:47:23 +00:00
if ( val ! = 0x4 )
2020-11-20 01:15:48 +00:00
break ;
}
2020-11-26 18:47:23 +00:00
switch ( val ) {
case 0x0 :
break ;
case 0x4 :
isp_prt ( isp , ISP_LOGERR , " The ROM code is busy after 50ms. " ) ;
return ;
case 0xf :
isp_prt ( isp , ISP_LOGERR , " Board configuration error. " ) ;
return ;
default :
isp_prt ( isp , ISP_LOGERR , " Unknown RISC Status Code 0x%x. " , val ) ;
2020-11-20 01:15:48 +00:00
return ;
1998-04-22 17:54:58 +00:00
}
1999-01-30 07:29:00 +00:00
/*
* Reset RISC Processor
*/
2020-11-20 01:15:48 +00:00
ISP_WRITE ( isp , BIU2400_HCCR , HCCR_2400_CMD_RESET ) ;
ISP_WRITE ( isp , BIU2400_HCCR , HCCR_2400_CMD_RELEASE ) ;
ISP_WRITE ( isp , BIU2400_HCCR , HCCR_2400_CMD_CLEAR_RESET ) ;
1998-04-22 17:54:58 +00:00
1999-01-10 02:55:10 +00:00
/*
2006-11-02 03:21:32 +00:00
* Post - RISC Reset stuff .
1999-01-10 02:55:10 +00:00
*/
2020-11-26 18:47:23 +00:00
for ( loops = 0 ; loops < 10000 ; loops + + ) {
2020-11-20 01:15:48 +00:00
ISP_DELAY ( 5 ) ;
val = ISP_READ ( isp , OUTMAILBOX0 ) ;
2020-11-26 18:47:23 +00:00
if ( val ! = 0x4 )
2020-11-20 01:15:48 +00:00
break ;
1998-04-22 17:54:58 +00:00
}
2020-11-26 18:47:23 +00:00
switch ( val ) {
case 0x0 :
break ;
case 0x4 :
isp_prt ( isp , ISP_LOGERR , " The ROM code is busy after 50ms. " ) ;
return ;
case 0xf :
isp_prt ( isp , ISP_LOGERR , " Board configuration error. " ) ;
return ;
default :
isp_prt ( isp , ISP_LOGERR , " Unknown RISC Status Code 0x%x. " , val ) ;
2020-11-20 01:15:48 +00:00
return ;
2009-08-01 01:04:26 +00:00
}
1998-04-22 17:54:58 +00:00
2020-11-24 04:16:49 +00:00
isp - > isp_reqidx = isp - > isp_reqodx = 0 ;
isp - > isp_resodx = 0 ;
isp - > isp_atioodx = 0 ;
2020-11-20 01:15:48 +00:00
ISP_WRITE ( isp , BIU2400_REQINP , 0 ) ;
ISP_WRITE ( isp , BIU2400_REQOUTP , 0 ) ;
ISP_WRITE ( isp , BIU2400_RSPINP , 0 ) ;
ISP_WRITE ( isp , BIU2400_RSPOUTP , 0 ) ;
if ( ! IS_26XX ( isp ) ) {
ISP_WRITE ( isp , BIU2400_PRI_REQINP , 0 ) ;
ISP_WRITE ( isp , BIU2400_PRI_REQOUTP , 0 ) ;
2017-03-14 08:03:56 +00:00
}
2020-11-20 01:15:48 +00:00
ISP_WRITE ( isp , BIU2400_ATIO_RSPINP , 0 ) ;
ISP_WRITE ( isp , BIU2400_ATIO_RSPOUTP , 0 ) ;
1998-04-22 17:54:58 +00:00
1999-01-30 07:29:00 +00:00
/*
* Up until this point we ' ve done everything by just reading or
* setting registers . From this point on we rely on at least * some *
* kind of firmware running in the card .
*/
1998-04-22 17:54:58 +00:00
/*
2009-08-01 01:04:26 +00:00
* Do some sanity checking by running a NOP command .
* If it succeeds , the ROM firmware is now running .
1998-04-22 17:54:58 +00:00
*/
2012-06-17 21:39:40 +00:00
MBSINIT ( & mbs , MBOX_NO_OP , MBLOGALL , 0 ) ;
2006-11-02 03:21:32 +00:00
isp_mboxcmd ( isp , & mbs ) ;
1998-04-22 17:54:58 +00:00
if ( mbs . param [ 0 ] ! = MBOX_COMMAND_COMPLETE ) {
2010-02-03 21:09:32 +00:00
isp_prt ( isp , ISP_LOGERR , " NOP command failed (%x) " , mbs . param [ 0 ] ) ;
1998-04-22 17:54:58 +00:00
return ;
}
2009-08-01 01:04:26 +00:00
/*
* Do some operational tests
*/
2020-11-20 01:15:48 +00:00
{
2012-06-17 21:39:40 +00:00
static const uint16_t patterns [ MAX_MAILBOX ] = {
0x0000 , 0xdead , 0xbeef , 0xffff ,
0xa5a5 , 0x5a5a , 0x7f7f , 0x7ff7 ,
0x3421 , 0xabcd , 0xdcba , 0xfeef ,
0xbead , 0xdebe , 0x2222 , 0x3333 ,
0x5555 , 0x6666 , 0x7777 , 0xaaaa ,
0xffff , 0xdddd , 0x9999 , 0x1fbc ,
0x6666 , 0x6677 , 0x1122 , 0x33ff ,
0x0000 , 0x0001 , 0x1000 , 0x1010 ,
} ;
2012-06-25 03:06:29 +00:00
int nmbox = ISP_NMBOX ( isp ) ;
2012-06-17 21:39:40 +00:00
MBSINIT ( & mbs , MBOX_MAILBOX_REG_TEST , MBLOGALL , 0 ) ;
2012-06-25 03:06:29 +00:00
for ( i = 1 ; i < nmbox ; i + + ) {
2012-06-17 21:39:40 +00:00
mbs . param [ i ] = patterns [ i ] ;
}
2006-11-02 03:21:32 +00:00
isp_mboxcmd ( isp , & mbs ) ;
1998-04-22 17:54:58 +00:00
if ( mbs . param [ 0 ] ! = MBOX_COMMAND_COMPLETE ) {
return ;
}
2012-06-25 03:06:29 +00:00
for ( i = 1 ; i < nmbox ; i + + ) {
2012-06-17 21:39:40 +00:00
if ( mbs . param [ i ] ! = patterns [ i ] ) {
isp_prt ( isp , ISP_LOGERR , " Register Test Failed at Register %d: should have 0x%04x but got 0x%04x " , i , patterns [ i ] , mbs . param [ i ] ) ;
return ;
}
1998-04-22 17:54:58 +00:00
}
}
/*
* Download new Firmware , unless requested not to do so .
* This is made slightly trickier in some cases where the
* firmware of the ROM revision is newer than the revision
* compiled into the driver . So , where we used to compare
* versions of our f / w and the ROM f / w , now we just see
* whether we have f / w at all and whether a config flag
* has disabled our download .
*/
2009-08-01 01:04:26 +00:00
if ( ( isp - > isp_mdvec - > dv_ispfw = = NULL ) | | ( isp - > isp_confopts & ISP_CFG_NORELOAD ) ) {
1998-04-22 17:54:58 +00:00
dodnld = 0 ;
2017-03-14 08:03:56 +00:00
} else {
/*
* Set up DMA for the request and response queues .
* We do this now so we can use the request queue
* for dma to load firmware from .
*/
if ( ISP_MBOXDMASETUP ( isp ) ! = 0 ) {
isp_prt ( isp , ISP_LOGERR , " Cannot setup DMA " ) ;
return ;
}
1998-04-22 17:54:58 +00:00
}
2020-11-20 01:15:48 +00:00
code_org = ISP_CODE_ORG_2400 ;
2020-11-26 18:47:23 +00:00
loaded_fw = 0 ;
2020-11-20 01:15:48 +00:00
if ( dodnld ) {
2007-03-22 23:38:32 +00:00
const uint32_t * ptr = isp - > isp_mdvec - > dv_ispfw ;
2017-03-14 17:34:44 +00:00
uint32_t la , wi , wl ;
2006-11-02 03:21:32 +00:00
/*
* Keep loading until we run out of f / w .
*/
code_org = ptr [ 2 ] ; /* 1st load address is our start addr */
for ( ; ; ) {
2009-08-01 01:04:26 +00:00
isp_prt ( isp , ISP_LOGDEBUG0 , " load 0x%x words of code at load address 0x%x " , ptr [ 3 ] , ptr [ 2 ] ) ;
2006-11-02 03:21:32 +00:00
wi = 0 ;
la = ptr [ 2 ] ;
wl = ptr [ 3 ] ;
while ( wi < ptr [ 3 ] ) {
uint32_t * cp ;
uint32_t nw ;
2017-03-14 17:34:44 +00:00
nw = min ( wl , ISP_QUEUE_SIZE ( RQUEST_QUEUE_LEN ( isp ) ) / 4 ) ;
2006-11-02 03:21:32 +00:00
cp = isp - > isp_rquest ;
2017-03-14 17:34:44 +00:00
for ( i = 0 ; i < nw ; i + + )
ISP_IOXPUT_32 ( isp , ptr [ wi + i ] , & cp [ i ] ) ;
2011-02-14 21:50:51 +00:00
MEMORYBARRIER ( isp , SYNC_REQUEST , 0 , ISP_QUEUE_SIZE ( RQUEST_QUEUE_LEN ( isp ) ) , - 1 ) ;
2017-03-14 17:34:44 +00:00
MBSINIT ( & mbs , MBOX_LOAD_RISC_RAM , MBLOGALL , 0 ) ;
mbs . param [ 1 ] = la ;
mbs . param [ 2 ] = DMA_WD1 ( isp - > isp_rquest_dma ) ;
mbs . param [ 3 ] = DMA_WD0 ( isp - > isp_rquest_dma ) ;
mbs . param [ 4 ] = nw > > 16 ;
mbs . param [ 5 ] = nw ;
mbs . param [ 6 ] = DMA_WD3 ( isp - > isp_rquest_dma ) ;
mbs . param [ 7 ] = DMA_WD2 ( isp - > isp_rquest_dma ) ;
mbs . param [ 8 ] = la > > 16 ;
isp_prt ( isp , ISP_LOGDEBUG0 , " LOAD RISC RAM %u words at load address 0x%x " , nw , la ) ;
2006-11-02 03:21:32 +00:00
isp_mboxcmd ( isp , & mbs ) ;
if ( mbs . param [ 0 ] ! = MBOX_COMMAND_COMPLETE ) {
2017-03-14 17:34:44 +00:00
isp_prt ( isp , ISP_LOGERR , " F/W download failed " ) ;
2006-11-02 03:21:32 +00:00
return ;
}
la + = nw ;
2017-03-14 17:34:44 +00:00
wi + = nw ;
wl - = nw ;
2006-11-02 03:21:32 +00:00
}
if ( ptr [ 1 ] = = 0 ) {
break ;
}
ptr + = ptr [ 3 ] ;
2009-08-01 01:04:26 +00:00
}
2020-11-26 18:47:23 +00:00
loaded_fw = 1 ;
2015-12-02 20:22:50 +00:00
} else if ( IS_26XX ( isp ) ) {
2018-03-15 01:07:21 +00:00
isp_prt ( isp , ISP_LOGDEBUG1 , " loading firmware from flash " ) ;
2015-12-02 20:22:50 +00:00
MBSINIT ( & mbs , MBOX_LOAD_FLASH_FIRMWARE , MBLOGALL , 5000000 ) ;
mbs . ibitm = 0x01 ;
mbs . obitm = 0x07 ;
isp_mboxcmd ( isp , & mbs ) ;
if ( mbs . param [ 0 ] ! = MBOX_COMMAND_COMPLETE ) {
isp_prt ( isp , ISP_LOGERR , " Flash F/W load failed " ) ;
return ;
}
2009-08-01 01:04:26 +00:00
} else {
isp_prt ( isp , ISP_LOGDEBUG2 , " skipping f/w download " ) ;
}
/*
* If we loaded firmware , verify its checksum
*/
2020-11-26 18:47:23 +00:00
if ( loaded_fw ) {
2012-06-17 21:39:40 +00:00
MBSINIT ( & mbs , MBOX_VERIFY_CHECKSUM , MBLOGNONE , 0 ) ;
2020-11-20 01:15:48 +00:00
mbs . param [ 1 ] = code_org > > 16 ;
mbs . param [ 2 ] = code_org ;
2006-11-02 03:21:32 +00:00
isp_mboxcmd ( isp , & mbs ) ;
if ( mbs . param [ 0 ] ! = MBOX_COMMAND_COMPLETE ) {
isp_prt ( isp , ISP_LOGERR , dcrc ) ;
return ;
2006-08-14 05:42:46 +00:00
}
1998-04-22 17:54:58 +00:00
}
/*
* Now start it rolling .
*
* If we didn ' t actually download f / w ,
* we still need to ( re ) start it .
*/
2012-06-17 21:39:40 +00:00
MBSINIT ( & mbs , MBOX_EXEC_FIRMWARE , MBLOGALL , 5000000 ) ;
2020-11-26 18:47:23 +00:00
mbs . param [ 1 ] = code_org > > 16 ;
mbs . param [ 2 ] = code_org ;
if ( ! IS_26XX ( isp ) )
mbs . param [ 3 ] = loaded_fw ? 0 : 1 ;
2006-11-02 03:21:32 +00:00
isp_mboxcmd ( isp , & mbs ) ;
2020-11-20 01:15:48 +00:00
if ( mbs . param [ 0 ] ! = MBOX_COMMAND_COMPLETE )
return ;
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
2009-08-01 01:04:26 +00:00
/*
* Ask the chip for the current firmware version .
* This should prove that the new firmware is working .
*/
2018-03-15 01:07:21 +00:00
MBSINIT ( & mbs , MBOX_ABOUT_FIRMWARE , MBLOGALL , 5000000 ) ;
2006-11-02 03:21:32 +00:00
isp_mboxcmd ( isp , & mbs ) ;
1998-04-22 17:54:58 +00:00
if ( mbs . param [ 0 ] ! = MBOX_COMMAND_COMPLETE ) {
return ;
}
2001-09-03 03:09:48 +00:00
2020-11-20 01:15:48 +00:00
isp - > isp_fwrev [ 0 ] = mbs . param [ 1 ] ;
isp - > isp_fwrev [ 1 ] = mbs . param [ 2 ] ;
isp - > isp_fwrev [ 2 ] = mbs . param [ 3 ] ;
isp - > isp_fwattr = mbs . param [ 6 ] ;
isp - > isp_fwattr | = ( ( uint64_t ) mbs . param [ 15 ] ) < < 16 ;
if ( isp - > isp_fwattr & ISP2400_FW_ATTR_EXTNDED ) {
isp - > isp_fwattr | =
( ( ( uint64_t ) mbs . param [ 16 ] ) < < 32 ) |
( ( ( uint64_t ) mbs . param [ 17 ] ) < < 48 ) ;
1998-09-15 08:42:56 +00:00
}
1999-10-17 18:58:22 +00:00
2012-06-17 21:39:40 +00:00
isp_prt ( isp , ISP_LOGCONFIG , " Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d " ,
btype , isp - > isp_revision , dodnld ? " loaded " : " resident " , isp - > isp_fwrev [ 0 ] , isp - > isp_fwrev [ 1 ] , isp - > isp_fwrev [ 2 ] ) ;
fwt = isp - > isp_fwattr ;
2020-11-20 01:15:48 +00:00
buf = FCPARAM ( isp , 0 ) - > isp_scanscratch ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN , " Attributes: " ) ;
if ( fwt & ISP2400_FW_ATTR_CLASS2 ) {
fwt ^ = ISP2400_FW_ATTR_CLASS2 ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s Class2 " , buf ) ;
}
if ( fwt & ISP2400_FW_ATTR_IP ) {
fwt ^ = ISP2400_FW_ATTR_IP ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s IP " , buf ) ;
}
if ( fwt & ISP2400_FW_ATTR_MULTIID ) {
fwt ^ = ISP2400_FW_ATTR_MULTIID ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s MultiID " , buf ) ;
}
if ( fwt & ISP2400_FW_ATTR_SB2 ) {
fwt ^ = ISP2400_FW_ATTR_SB2 ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s SB2 " , buf ) ;
}
if ( fwt & ISP2400_FW_ATTR_T10CRC ) {
fwt ^ = ISP2400_FW_ATTR_T10CRC ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s T10CRC " , buf ) ;
}
if ( fwt & ISP2400_FW_ATTR_VI ) {
fwt ^ = ISP2400_FW_ATTR_VI ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s VI " , buf ) ;
}
if ( fwt & ISP2400_FW_ATTR_MQ ) {
fwt ^ = ISP2400_FW_ATTR_MQ ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s MQ " , buf ) ;
}
if ( fwt & ISP2400_FW_ATTR_MSIX ) {
fwt ^ = ISP2400_FW_ATTR_MSIX ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s MSIX " , buf ) ;
}
if ( fwt & ISP2400_FW_ATTR_FCOE ) {
fwt ^ = ISP2400_FW_ATTR_FCOE ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s FCOE " , buf ) ;
}
if ( fwt & ISP2400_FW_ATTR_VP0 ) {
fwt ^ = ISP2400_FW_ATTR_VP0 ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s VP0_Decoupling " , buf ) ;
}
if ( fwt & ISP2400_FW_ATTR_EXPFW ) {
fwt ^ = ISP2400_FW_ATTR_EXPFW ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s (Experimental) " , buf ) ;
}
if ( fwt & ISP2400_FW_ATTR_HOTFW ) {
fwt ^ = ISP2400_FW_ATTR_HOTFW ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s HotFW " , buf ) ;
}
fwt & = ~ ISP2400_FW_ATTR_EXTNDED ;
if ( fwt & ISP2400_FW_ATTR_EXTVP ) {
fwt ^ = ISP2400_FW_ATTR_EXTVP ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s ExtVP " , buf ) ;
}
if ( fwt & ISP2400_FW_ATTR_VN2VN ) {
fwt ^ = ISP2400_FW_ATTR_VN2VN ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s VN2VN " , buf ) ;
2012-06-17 21:39:40 +00:00
}
2020-11-20 01:15:48 +00:00
if ( fwt & ISP2400_FW_ATTR_EXMOFF ) {
fwt ^ = ISP2400_FW_ATTR_EXMOFF ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s EXMOFF " , buf ) ;
}
if ( fwt & ISP2400_FW_ATTR_NPMOFF ) {
fwt ^ = ISP2400_FW_ATTR_NPMOFF ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s NPMOFF " , buf ) ;
}
if ( fwt & ISP2400_FW_ATTR_DIFCHOP ) {
fwt ^ = ISP2400_FW_ATTR_DIFCHOP ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s DIFCHOP " , buf ) ;
}
if ( fwt & ISP2400_FW_ATTR_SRIOV ) {
fwt ^ = ISP2400_FW_ATTR_SRIOV ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s SRIOV " , buf ) ;
}
if ( fwt & ISP2400_FW_ATTR_ASICTMP ) {
fwt ^ = ISP2400_FW_ATTR_ASICTMP ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s ASICTMP " , buf ) ;
}
if ( fwt & ISP2400_FW_ATTR_ATIOMQ ) {
fwt ^ = ISP2400_FW_ATTR_ATIOMQ ;
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s ATIOMQ " , buf ) ;
}
if ( fwt ) {
ISP_SNPRINTF ( buf , ISP_FC_SCRLEN - strlen ( buf ) , " %s (unknown 0x%08x%08x) " , buf ,
( uint32_t ) ( fwt > > 32 ) , ( uint32_t ) fwt ) ;
}
isp_prt ( isp , ISP_LOGCONFIG , " %s " , buf ) ;
2012-06-17 21:39:40 +00:00
2020-11-24 04:16:49 +00:00
/*
* For the maximum number of commands take free exchange control block
* buffer count reported by firmware , limiting it to the maximum of our
* hardcoded handle format ( 16 K now ) minus some management reserve .
*/
2020-11-20 01:15:48 +00:00
MBSINIT ( & mbs , MBOX_GET_RESOURCE_COUNT , MBLOGALL , 0 ) ;
isp_mboxcmd ( isp , & mbs ) ;
2020-11-24 04:16:49 +00:00
if ( mbs . param [ 0 ] ! = MBOX_COMMAND_COMPLETE )
2020-11-20 01:15:48 +00:00
return ;
2020-11-24 04:16:49 +00:00
isp - > isp_maxcmds = MIN ( mbs . param [ 3 ] , ISP_HANDLE_MAX - ISP_HANDLE_RESERVE ) ;
2009-08-01 01:04:26 +00:00
isp_prt ( isp , ISP_LOGCONFIG , " %d max I/O command limit set " , isp - > isp_maxcmds ) ;
/*
* If we don ' t have Multi - ID f / w loaded , we need to restrict channels to one .
* Only make this check for non - SCSI cards ( I ' m not sure firmware attributes
* work for them ) .
*/
2020-11-20 01:15:48 +00:00
if ( isp - > isp_nchan > 1 ) {
2014-11-26 15:03:21 +00:00
if ( ! ISP_CAP_MULTI_ID ( isp ) ) {
2015-10-26 18:14:15 +00:00
isp_prt ( isp , ISP_LOGWARN , " non-MULTIID f/w loaded, "
" only can enable 1 of %d channels " , isp - > isp_nchan ) ;
isp - > isp_nchan = 1 ;
} else if ( ! ISP_CAP_VP0 ( isp ) ) {
isp_prt ( isp , ISP_LOGWARN , " We can not use MULTIID "
" feature properly without VP0_Decoupling " ) ;
2012-06-24 17:30:54 +00:00
isp - > isp_nchan = 1 ;
}
2009-08-01 01:04:26 +00:00
}
2017-03-14 08:03:56 +00:00
/*
* Final DMA setup after we got isp_maxcmds .
*/
if ( ISP_MBOXDMASETUP ( isp ) ! = 0 ) {
isp_prt ( isp , ISP_LOGERR , " Cannot setup DMA " ) ;
return ;
}
/*
* Setup interrupts .
*/
if ( ISP_IRQSETUP ( isp ) ! = 0 ) {
isp_prt ( isp , ISP_LOGERR , " Cannot setup IRQ " ) ;
return ;
}
ISP_ENABLE_INTS ( isp ) ;
2020-11-20 01:15:48 +00:00
for ( i = 0 ; i < isp - > isp_nchan ; i + + )
isp_change_fw_state ( isp , i , FW_CONFIG_WAIT ) ;
1999-10-17 18:58:22 +00:00
1998-04-22 17:54:58 +00:00
isp - > isp_state = ISP_RESETSTATE ;
2000-06-18 04:56:17 +00:00
2007-01-20 04:00:21 +00:00
/*
2009-08-01 01:04:26 +00:00
* We get some default values established . As a side
* effect , NVRAM is read here ( unless overriden by
* a configuration flag ) .
2007-01-20 04:00:21 +00:00
*/
2009-08-01 01:04:26 +00:00
if ( do_load_defaults ) {
2020-11-20 01:15:48 +00:00
for ( i = 0 ; i < isp - > isp_nchan ; i + + )
isp_setdfltfcparm ( isp , i ) ;
2007-01-20 04:00:21 +00:00
}
1998-04-22 17:54:58 +00:00
}
2015-11-22 15:57:54 +00:00
/*
* Clean firmware shutdown .
*/
static int
2017-03-14 08:03:56 +00:00
isp_stop ( ispsoftc_t * isp )
2015-11-22 15:57:54 +00:00
{
mbreg_t mbs ;
isp - > isp_state = ISP_NILSTATE ;
MBSINIT ( & mbs , MBOX_STOP_FIRMWARE , MBLOGALL , 500000 ) ;
mbs . param [ 1 ] = 0 ;
mbs . param [ 2 ] = 0 ;
mbs . param [ 3 ] = 0 ;
mbs . param [ 4 ] = 0 ;
mbs . param [ 5 ] = 0 ;
mbs . param [ 6 ] = 0 ;
mbs . param [ 7 ] = 0 ;
mbs . param [ 8 ] = 0 ;
isp_mboxcmd ( isp , & mbs ) ;
return ( mbs . param [ 0 ] = = MBOX_COMMAND_COMPLETE ? 0 : mbs . param [ 0 ] ) ;
}
2017-03-14 08:03:56 +00:00
/*
* Hardware shutdown .
*/
void
isp_shutdown ( ispsoftc_t * isp )
{
if ( isp - > isp_state > = ISP_RESETSTATE )
isp_stop ( isp ) ;
ISP_DISABLE_INTS ( isp ) ;
2020-11-20 01:15:48 +00:00
ISP_WRITE ( isp , BIU2400_ICR , 0 ) ;
ISP_WRITE ( isp , BIU2400_HCCR , HCCR_2400_CMD_PAUSE ) ;
2017-03-14 08:03:56 +00:00
}
1998-04-22 17:54:58 +00:00
/*
1999-01-30 07:29:00 +00:00
* Initialize Parameters of Hardware to a known state .
1998-09-15 08:42:56 +00:00
*
* Locks are held before coming here .
1998-04-22 17:54:58 +00:00
*/
void
2006-04-21 18:30:01 +00:00
isp_init ( ispsoftc_t * isp )
2001-02-11 03:44:43 +00:00
{
2006-11-02 03:21:32 +00:00
fcparam * fcp ;
isp_icb_2400_t local , * icbp = & local ;
2001-02-11 03:44:43 +00:00
mbreg_t mbs ;
2009-08-01 01:04:26 +00:00
int chan ;
2017-07-27 15:33:57 +00:00
int ownloopid = 0 ;
2009-08-01 01:04:26 +00:00
/*
* Check to see whether all channels have * some * kind of role
*/
for ( chan = 0 ; chan < isp - > isp_nchan ; chan + + ) {
fcp = FCPARAM ( isp , chan ) ;
if ( fcp - > role ! = ISP_ROLE_NONE ) {
break ;
}
}
if ( chan = = isp - > isp_nchan ) {
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
isp_prt ( isp , ISP_LOG_WARN1 , " all %d channels with role 'none' " , chan ) ;
2009-08-01 01:04:26 +00:00
return ;
}
2006-11-02 03:21:32 +00:00
2015-10-25 10:49:05 +00:00
isp - > isp_state = ISP_INITSTATE ;
2009-08-01 01:04:26 +00:00
/*
* Start with channel 0.
*/
fcp = FCPARAM ( isp , 0 ) ;
2001-02-11 03:44:43 +00:00
2006-11-02 03:21:32 +00:00
/*
* Turn on LIP F8 async event ( 1 )
*/
2009-08-01 01:04:26 +00:00
MBSINIT ( & mbs , MBOX_SET_FIRMWARE_OPTIONS , MBLOGALL , 0 ) ;
2006-11-02 03:21:32 +00:00
mbs . param [ 1 ] = 1 ;
isp_mboxcmd ( isp , & mbs ) ;
if ( mbs . param [ 0 ] ! = MBOX_COMMAND_COMPLETE ) {
return ;
2001-02-11 03:44:43 +00:00
}
2009-08-01 01:04:26 +00:00
ISP_MEMZERO ( icbp , sizeof ( * icbp ) ) ;
icbp - > icb_fwoptions1 = fcp - > isp_fwoptions ;
2015-10-25 16:04:31 +00:00
icbp - > icb_fwoptions2 = fcp - > isp_xfwoptions ;
icbp - > icb_fwoptions3 = fcp - > isp_zfwoptions ;
2015-10-26 18:14:15 +00:00
if ( isp - > isp_nchan > 1 & & ISP_CAP_VP0 ( isp ) ) {
2009-08-01 01:04:26 +00:00
icbp - > icb_fwoptions1 & = ~ ICB2400_OPT1_INI_DISABLE ;
2015-10-25 16:04:31 +00:00
icbp - > icb_fwoptions1 | = ICB2400_OPT1_TGT_ENABLE ;
2006-11-02 03:21:32 +00:00
} else {
2015-10-25 16:04:31 +00:00
if ( fcp - > role & ISP_ROLE_TARGET )
icbp - > icb_fwoptions1 | = ICB2400_OPT1_TGT_ENABLE ;
else
icbp - > icb_fwoptions1 & = ~ ICB2400_OPT1_TGT_ENABLE ;
if ( fcp - > role & ISP_ROLE_INITIATOR )
icbp - > icb_fwoptions1 & = ~ ICB2400_OPT1_INI_DISABLE ;
else
icbp - > icb_fwoptions1 | = ICB2400_OPT1_INI_DISABLE ;
2006-11-02 03:21:32 +00:00
}
icbp - > icb_version = ICB_VERSION1 ;
2009-08-01 01:04:26 +00:00
icbp - > icb_maxfrmlen = DEFAULT_FRAMESIZE ( isp ) ;
if ( icbp - > icb_maxfrmlen < ICB_MIN_FRMLEN | | icbp - > icb_maxfrmlen > ICB_MAX_FRMLEN ) {
isp_prt ( isp , ISP_LOGERR , " bad frame length (%d) from NVRAM- using %d " , DEFAULT_FRAMESIZE ( isp ) , ICB_DFLT_FRMLEN ) ;
2006-11-02 03:21:32 +00:00
icbp - > icb_maxfrmlen = ICB_DFLT_FRMLEN ;
}
2020-11-22 02:51:30 +00:00
if ( ! IS_26XX ( isp ) )
icbp - > icb_execthrottle = 0xffff ;
2006-11-02 03:21:32 +00:00
2020-11-22 05:42:52 +00:00
# ifdef ISP_TARGET_MODE
2012-06-24 17:30:54 +00:00
/*
* Set target exchange count . Take half if we are supporting both roles .
*/
2009-08-01 01:04:26 +00:00
if ( icbp - > icb_fwoptions1 & ICB2400_OPT1_TGT_ENABLE ) {
2012-06-24 17:30:54 +00:00
if ( ( icbp - > icb_fwoptions1 & ICB2400_OPT1_INI_DISABLE ) = = 0 )
2020-11-22 04:29:55 +00:00
icbp - > icb_xchgcnt = MIN ( isp - > isp_maxcmds / 2 , ATPDPSIZE ) ;
else
icbp - > icb_xchgcnt = isp - > isp_maxcmds ;
2006-11-02 03:21:32 +00:00
}
2020-11-22 05:42:52 +00:00
# endif
2017-07-27 15:33:57 +00:00
ownloopid = ( isp - > isp_confopts & ISP_CFG_OWNLOOPID ) ! = 0 ;
icbp - > icb_hardaddr = fcp - > isp_loopid ;
if ( icbp - > icb_hardaddr > = LOCAL_LOOP_LIM ) {
icbp - > icb_hardaddr = 0 ;
ownloopid = 0 ;
2006-11-02 03:21:32 +00:00
}
2017-07-27 15:33:57 +00:00
if ( ownloopid )
icbp - > icb_fwoptions1 | = ICB2400_OPT1_HARD_ADDRESS ;
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
if ( isp - > isp_confopts & ISP_CFG_NOFCTAPE ) {
icbp - > icb_fwoptions2 & = ~ ICB2400_OPT2_FCTAPE ;
}
if ( isp - > isp_confopts & ISP_CFG_FCTAPE ) {
icbp - > icb_fwoptions2 | = ICB2400_OPT2_FCTAPE ;
}
2015-10-21 08:23:19 +00:00
for ( chan = 0 ; chan < isp - > isp_nchan ; chan + + ) {
if ( icbp - > icb_fwoptions2 & ICB2400_OPT2_FCTAPE )
FCPARAM ( isp , chan ) - > fctape_enabled = 1 ;
else
FCPARAM ( isp , chan ) - > fctape_enabled = 0 ;
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
}
2009-08-01 01:04:26 +00:00
switch ( isp - > isp_confopts & ISP_CFG_PORT_PREF ) {
2006-11-02 03:21:32 +00:00
case ISP_CFG_LPORT_ONLY :
icbp - > icb_fwoptions2 & = ~ ICB2400_OPT2_TOPO_MASK ;
icbp - > icb_fwoptions2 | = ICB2400_OPT2_LOOP_ONLY ;
break ;
2016-04-13 07:04:04 +00:00
case ISP_CFG_NPORT_ONLY :
icbp - > icb_fwoptions2 & = ~ ICB2400_OPT2_TOPO_MASK ;
icbp - > icb_fwoptions2 | = ICB2400_OPT2_PTP_ONLY ;
break ;
case ISP_CFG_NPORT :
2012-06-17 21:39:40 +00:00
/* ISP_CFG_PTP_2_LOOP not available in 24XX/25XX */
2016-04-13 07:04:04 +00:00
case ISP_CFG_LPORT :
2006-11-02 03:21:32 +00:00
icbp - > icb_fwoptions2 & = ~ ICB2400_OPT2_TOPO_MASK ;
icbp - > icb_fwoptions2 | = ICB2400_OPT2_LOOP_2_PTP ;
break ;
2016-04-13 07:04:04 +00:00
default :
/* Let NVRAM settings define it if they are sane */
switch ( icbp - > icb_fwoptions2 & ICB2400_OPT2_TOPO_MASK ) {
case ICB2400_OPT2_LOOP_ONLY :
case ICB2400_OPT2_PTP_ONLY :
case ICB2400_OPT2_LOOP_2_PTP :
break ;
default :
icbp - > icb_fwoptions2 & = ~ ICB2400_OPT2_TOPO_MASK ;
icbp - > icb_fwoptions2 | = ICB2400_OPT2_LOOP_2_PTP ;
}
break ;
2006-11-02 03:21:32 +00:00
}
switch ( icbp - > icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK ) {
case ICB2400_OPT2_ZIO :
case ICB2400_OPT2_ZIO1 :
icbp - > icb_idelaytimer = 0 ;
break ;
case 0 :
break ;
default :
2009-08-01 01:04:26 +00:00
isp_prt ( isp , ISP_LOGWARN , " bad value %x in fwopt2 timer field " , icbp - > icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK ) ;
2006-11-02 03:21:32 +00:00
icbp - > icb_fwoptions2 & = ~ ICB2400_OPT2_TIMER_MASK ;
break ;
}
2015-12-03 22:55:40 +00:00
if ( IS_26XX ( isp ) ) {
2017-03-19 19:11:40 +00:00
/* Use handshake to reduce global lock congestion. */
2015-12-03 22:55:40 +00:00
icbp - > icb_fwoptions2 | = ICB2400_OPT2_ENA_IHR ;
icbp - > icb_fwoptions2 | = ICB2400_OPT2_ENA_IHA ;
}
2012-06-17 21:39:40 +00:00
if ( ( icbp - > icb_fwoptions3 & ICB2400_OPT3_RSPSZ_MASK ) = = 0 ) {
icbp - > icb_fwoptions3 | = ICB2400_OPT3_RSPSZ_24 ;
}
2015-12-02 20:22:50 +00:00
if ( isp - > isp_confopts & ISP_CFG_1GB ) {
2015-12-22 17:01:30 +00:00
icbp - > icb_fwoptions3 & = ~ ICB2400_OPT3_RATE_MASK ;
2015-12-02 20:22:50 +00:00
icbp - > icb_fwoptions3 | = ICB2400_OPT3_RATE_1GB ;
} else if ( isp - > isp_confopts & ISP_CFG_2GB ) {
2015-12-22 17:01:30 +00:00
icbp - > icb_fwoptions3 & = ~ ICB2400_OPT3_RATE_MASK ;
2015-12-02 20:22:50 +00:00
icbp - > icb_fwoptions3 | = ICB2400_OPT3_RATE_2GB ;
} else if ( isp - > isp_confopts & ISP_CFG_4GB ) {
2015-12-22 17:01:30 +00:00
icbp - > icb_fwoptions3 & = ~ ICB2400_OPT3_RATE_MASK ;
2015-12-02 20:22:50 +00:00
icbp - > icb_fwoptions3 | = ICB2400_OPT3_RATE_4GB ;
} else if ( isp - > isp_confopts & ISP_CFG_8GB ) {
2015-12-22 17:01:30 +00:00
icbp - > icb_fwoptions3 & = ~ ICB2400_OPT3_RATE_MASK ;
2015-12-02 20:22:50 +00:00
icbp - > icb_fwoptions3 | = ICB2400_OPT3_RATE_8GB ;
} else if ( isp - > isp_confopts & ISP_CFG_16GB ) {
2015-12-22 17:01:30 +00:00
icbp - > icb_fwoptions3 & = ~ ICB2400_OPT3_RATE_MASK ;
2015-12-02 20:22:50 +00:00
icbp - > icb_fwoptions3 | = ICB2400_OPT3_RATE_16GB ;
2018-02-28 16:24:32 +00:00
} else if ( isp - > isp_confopts & ISP_CFG_32GB ) {
icbp - > icb_fwoptions3 & = ~ ICB2400_OPT3_RATE_MASK ;
icbp - > icb_fwoptions3 | = ICB2400_OPT3_RATE_32GB ;
2006-11-02 03:21:32 +00:00
} else {
2015-12-22 17:01:30 +00:00
switch ( icbp - > icb_fwoptions3 & ICB2400_OPT3_RATE_MASK ) {
case ICB2400_OPT3_RATE_4GB :
case ICB2400_OPT3_RATE_8GB :
case ICB2400_OPT3_RATE_16GB :
2018-02-28 16:24:32 +00:00
case ICB2400_OPT3_RATE_32GB :
2015-12-22 17:01:30 +00:00
case ICB2400_OPT3_RATE_AUTO :
break ;
case ICB2400_OPT3_RATE_2GB :
if ( isp - > isp_type < = ISP_HA_FC_2500 )
break ;
/*FALLTHROUGH*/
case ICB2400_OPT3_RATE_1GB :
if ( isp - > isp_type < = ISP_HA_FC_2400 )
break ;
/*FALLTHROUGH*/
default :
icbp - > icb_fwoptions3 & = ~ ICB2400_OPT3_RATE_MASK ;
icbp - > icb_fwoptions3 | = ICB2400_OPT3_RATE_AUTO ;
break ;
}
2006-11-02 03:21:32 +00:00
}
2017-07-27 15:33:57 +00:00
if ( ownloopid = = 0 ) {
icbp - > icb_fwoptions3 | = ICB2400_OPT3_SOFTID ;
}
2006-11-02 03:21:32 +00:00
icbp - > icb_logintime = ICB_LOGIN_TOV ;
2015-06-25 10:03:38 +00:00
if ( fcp - > isp_wwnn & & fcp - > isp_wwpn ) {
2006-11-02 03:21:32 +00:00
icbp - > icb_fwoptions1 | = ICB2400_OPT1_BOTH_WWNS ;
2009-08-01 01:04:26 +00:00
MAKE_NODE_NAME_FROM_WWN ( icbp - > icb_portname , fcp - > isp_wwpn ) ;
MAKE_NODE_NAME_FROM_WWN ( icbp - > icb_nodename , fcp - > isp_wwnn ) ;
isp_prt ( isp , ISP_LOGDEBUG1 , " Setting ICB Node 0x%08x%08x Port 0x%08x%08x " , ( ( uint32_t ) ( fcp - > isp_wwnn > > 32 ) ) , ( ( uint32_t ) ( fcp - > isp_wwnn ) ) ,
( ( uint32_t ) ( fcp - > isp_wwpn > > 32 ) ) , ( ( uint32_t ) ( fcp - > isp_wwpn ) ) ) ;
} else if ( fcp - > isp_wwpn ) {
2006-11-02 03:21:32 +00:00
icbp - > icb_fwoptions1 & = ~ ICB2400_OPT1_BOTH_WWNS ;
2009-08-01 01:04:26 +00:00
MAKE_NODE_NAME_FROM_WWN ( icbp - > icb_portname , fcp - > isp_wwpn ) ;
isp_prt ( isp , ISP_LOGDEBUG1 , " Setting ICB Node to be same as Port 0x%08x%08x " , ( ( uint32_t ) ( fcp - > isp_wwpn > > 32 ) ) , ( ( uint32_t ) ( fcp - > isp_wwpn ) ) ) ;
2006-11-02 03:21:32 +00:00
} else {
isp_prt ( isp , ISP_LOGERR , " No valid WWNs to use " ) ;
return ;
}
2020-11-24 04:16:49 +00:00
icbp - > icb_rspnsin = isp - > isp_resodx ;
icbp - > icb_rqstout = isp - > isp_reqidx ;
2006-11-02 03:21:32 +00:00
icbp - > icb_retry_count = fcp - > isp_retry_count ;
icbp - > icb_rqstqlen = RQUEST_QUEUE_LEN ( isp ) ;
if ( icbp - > icb_rqstqlen < 8 ) {
2009-08-01 01:04:26 +00:00
isp_prt ( isp , ISP_LOGERR , " bad request queue length %d " , icbp - > icb_rqstqlen ) ;
2006-11-02 03:21:32 +00:00
return ;
}
icbp - > icb_rsltqlen = RESULT_QUEUE_LEN ( isp ) ;
if ( icbp - > icb_rsltqlen < 8 ) {
isp_prt ( isp , ISP_LOGERR , " bad result queue length %d " ,
icbp - > icb_rsltqlen ) ;
return ;
}
icbp - > icb_rqstaddr [ RQRSP_ADDR0015 ] = DMA_WD0 ( isp - > isp_rquest_dma ) ;
icbp - > icb_rqstaddr [ RQRSP_ADDR1631 ] = DMA_WD1 ( isp - > isp_rquest_dma ) ;
icbp - > icb_rqstaddr [ RQRSP_ADDR3247 ] = DMA_WD2 ( isp - > isp_rquest_dma ) ;
icbp - > icb_rqstaddr [ RQRSP_ADDR4863 ] = DMA_WD3 ( isp - > isp_rquest_dma ) ;
icbp - > icb_respaddr [ RQRSP_ADDR0015 ] = DMA_WD0 ( isp - > isp_result_dma ) ;
icbp - > icb_respaddr [ RQRSP_ADDR1631 ] = DMA_WD1 ( isp - > isp_result_dma ) ;
icbp - > icb_respaddr [ RQRSP_ADDR3247 ] = DMA_WD2 ( isp - > isp_result_dma ) ;
icbp - > icb_respaddr [ RQRSP_ADDR4863 ] = DMA_WD3 ( isp - > isp_result_dma ) ;
# ifdef ISP_TARGET_MODE
2009-08-01 01:04:26 +00:00
/* unconditionally set up the ATIO queue if we support target mode */
2020-11-24 04:16:49 +00:00
icbp - > icb_atio_in = isp - > isp_atioodx ;
2020-11-20 19:36:34 +00:00
icbp - > icb_atioqlen = ATIO_QUEUE_LEN ( isp ) ;
2009-08-01 01:04:26 +00:00
if ( icbp - > icb_atioqlen < 8 ) {
isp_prt ( isp , ISP_LOGERR , " bad ATIO queue length %d " , icbp - > icb_atioqlen ) ;
return ;
2006-11-02 03:21:32 +00:00
}
2009-08-01 01:04:26 +00:00
icbp - > icb_atioqaddr [ RQRSP_ADDR0015 ] = DMA_WD0 ( isp - > isp_atioq_dma ) ;
icbp - > icb_atioqaddr [ RQRSP_ADDR1631 ] = DMA_WD1 ( isp - > isp_atioq_dma ) ;
icbp - > icb_atioqaddr [ RQRSP_ADDR3247 ] = DMA_WD2 ( isp - > isp_atioq_dma ) ;
icbp - > icb_atioqaddr [ RQRSP_ADDR4863 ] = DMA_WD3 ( isp - > isp_atioq_dma ) ;
2020-11-20 01:15:48 +00:00
isp_prt ( isp , ISP_LOGDEBUG0 , " isp_init: atioq %04x%04x%04x%04x " , DMA_WD3 ( isp - > isp_atioq_dma ) , DMA_WD2 ( isp - > isp_atioq_dma ) ,
2009-08-01 01:04:26 +00:00
DMA_WD1 ( isp - > isp_atioq_dma ) , DMA_WD0 ( isp - > isp_atioq_dma ) ) ;
2006-11-02 03:21:32 +00:00
# endif
2017-03-19 19:11:40 +00:00
if ( ISP_CAP_MSIX ( isp ) & & isp - > isp_nirq > = 2 ) {
icbp - > icb_msixresp = 1 ;
if ( IS_26XX ( isp ) & & isp - > isp_nirq > = 3 )
icbp - > icb_msixatio = 2 ;
}
2020-11-20 01:15:48 +00:00
isp_prt ( isp , ISP_LOGDEBUG0 , " isp_init: fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x " , icbp - > icb_fwoptions1 , icbp - > icb_fwoptions2 , icbp - > icb_fwoptions3 ) ;
2006-11-02 03:21:32 +00:00
2020-11-20 01:15:48 +00:00
isp_prt ( isp , ISP_LOGDEBUG0 , " isp_init: rqst %04x%04x%04x%04x rsp %04x%04x%04x%04x " , DMA_WD3 ( isp - > isp_rquest_dma ) , DMA_WD2 ( isp - > isp_rquest_dma ) ,
2009-08-01 01:04:26 +00:00
DMA_WD1 ( isp - > isp_rquest_dma ) , DMA_WD0 ( isp - > isp_rquest_dma ) , DMA_WD3 ( isp - > isp_result_dma ) , DMA_WD2 ( isp - > isp_result_dma ) ,
2006-11-02 03:21:32 +00:00
DMA_WD1 ( isp - > isp_result_dma ) , DMA_WD0 ( isp - > isp_result_dma ) ) ;
2009-08-01 01:04:26 +00:00
if ( FC_SCRATCH_ACQUIRE ( isp , 0 ) ) {
isp_prt ( isp , ISP_LOGERR , sacq ) ;
return ;
2006-11-02 03:21:32 +00:00
}
2009-08-01 01:04:26 +00:00
ISP_MEMZERO ( fcp - > isp_scratch , ISP_FC_SCRLEN ) ;
2006-11-02 03:21:32 +00:00
isp_put_icb_2400 ( isp , icbp , fcp - > isp_scratch ) ;
2016-04-11 10:48:26 +00:00
if ( isp - > isp_dblev & ISP_LOGDEBUG1 ) {
2020-11-20 01:15:48 +00:00
isp_print_bytes ( isp , " isp_init " ,
2016-04-11 10:48:26 +00:00
sizeof ( * icbp ) , fcp - > isp_scratch ) ;
}
2006-11-02 03:21:32 +00:00
2009-08-01 01:04:26 +00:00
/*
* Now fill in information about any additional channels
*/
if ( isp - > isp_nchan > 1 ) {
isp_icb_2400_vpinfo_t vpinfo , * vdst ;
vp_port_info_t pi , * pdst ;
size_t amt = 0 ;
uint8_t * off ;
2015-11-17 14:13:55 +00:00
vpinfo . vp_global_options = ICB2400_VPGOPT_GEN_RIDA ;
2015-10-26 18:14:15 +00:00
if ( ISP_CAP_VP0 ( isp ) ) {
2015-10-21 08:23:19 +00:00
vpinfo . vp_global_options | = ICB2400_VPGOPT_VP0_DECOUPLE ;
vpinfo . vp_count = isp - > isp_nchan ;
chan = 0 ;
} else {
vpinfo . vp_count = isp - > isp_nchan - 1 ;
chan = 1 ;
}
2009-08-01 01:04:26 +00:00
off = fcp - > isp_scratch ;
off + = ICB2400_VPINFO_OFF ;
vdst = ( isp_icb_2400_vpinfo_t * ) off ;
isp_put_icb_2400_vpinfo ( isp , & vpinfo , vdst ) ;
amt = ICB2400_VPINFO_OFF + sizeof ( isp_icb_2400_vpinfo_t ) ;
2015-10-21 08:23:19 +00:00
for ( ; chan < isp - > isp_nchan ; chan + + ) {
2009-08-01 01:04:26 +00:00
fcparam * fcp2 ;
ISP_MEMZERO ( & pi , sizeof ( pi ) ) ;
fcp2 = FCPARAM ( isp , chan ) ;
if ( fcp2 - > role ! = ISP_ROLE_NONE ) {
2015-11-17 14:13:55 +00:00
pi . vp_port_options = ICB2400_VPOPT_ENABLED |
ICB2400_VPOPT_ENA_SNSLOGIN ;
2015-10-21 08:23:19 +00:00
if ( fcp2 - > role & ISP_ROLE_INITIATOR )
2009-08-01 01:04:26 +00:00
pi . vp_port_options | = ICB2400_VPOPT_INI_ENABLE ;
2015-10-21 08:23:19 +00:00
if ( ( fcp2 - > role & ISP_ROLE_TARGET ) = = 0 )
2009-08-01 01:04:26 +00:00
pi . vp_port_options | = ICB2400_VPOPT_TGT_DISABLE ;
2017-07-27 15:33:57 +00:00
if ( fcp2 - > isp_loopid < LOCAL_LOOP_LIM ) {
pi . vp_port_loopid = fcp2 - > isp_loopid ;
if ( isp - > isp_confopts & ISP_CFG_OWNLOOPID )
pi . vp_port_options | = ICB2400_VPOPT_HARD_ADDRESS ;
}
2015-10-25 16:04:31 +00:00
}
2015-10-21 08:23:19 +00:00
MAKE_NODE_NAME_FROM_WWN ( pi . vp_port_portname , fcp2 - > isp_wwpn ) ;
MAKE_NODE_NAME_FROM_WWN ( pi . vp_port_nodename , fcp2 - > isp_wwnn ) ;
2009-08-01 01:04:26 +00:00
off = fcp - > isp_scratch ;
2015-10-26 18:14:15 +00:00
if ( ISP_CAP_VP0 ( isp ) )
2015-10-21 08:23:19 +00:00
off + = ICB2400_VPINFO_PORT_OFF ( chan ) ;
else
off + = ICB2400_VPINFO_PORT_OFF ( chan - 1 ) ;
2009-08-01 01:04:26 +00:00
pdst = ( vp_port_info_t * ) off ;
isp_put_vp_port_info ( isp , & pi , pdst ) ;
amt + = ICB2400_VPOPT_WRITE_SIZE ;
}
2015-06-22 08:26:28 +00:00
if ( isp - > isp_dblev & ISP_LOGDEBUG1 ) {
2020-11-20 01:15:48 +00:00
isp_print_bytes ( isp , " isp_init " ,
2015-06-22 08:26:28 +00:00
amt - ICB2400_VPINFO_OFF ,
( char * ) fcp - > isp_scratch + ICB2400_VPINFO_OFF ) ;
}
2009-08-01 01:04:26 +00:00
}
2006-11-02 03:21:32 +00:00
/*
* Init the firmware
*/
2009-08-01 01:04:26 +00:00
MBSINIT ( & mbs , 0 , MBLOGALL , 30000000 ) ;
if ( isp - > isp_nchan > 1 ) {
mbs . param [ 0 ] = MBOX_INIT_FIRMWARE_MULTI_ID ;
} else {
mbs . param [ 0 ] = MBOX_INIT_FIRMWARE ;
}
2015-10-20 10:16:03 +00:00
mbs . param [ 1 ] = 0 ;
2006-11-02 03:21:32 +00:00
mbs . param [ 2 ] = DMA_WD1 ( fcp - > isp_scdma ) ;
mbs . param [ 3 ] = DMA_WD0 ( fcp - > isp_scdma ) ;
mbs . param [ 6 ] = DMA_WD3 ( fcp - > isp_scdma ) ;
mbs . param [ 7 ] = DMA_WD2 ( fcp - > isp_scdma ) ;
2009-08-01 01:04:26 +00:00
isp_prt ( isp , ISP_LOGDEBUG0 , " INIT F/W from %04x%04x%04x%04x " , DMA_WD3 ( fcp - > isp_scdma ) , DMA_WD2 ( fcp - > isp_scdma ) , DMA_WD1 ( fcp - > isp_scdma ) , DMA_WD0 ( fcp - > isp_scdma ) ) ;
2011-02-14 21:50:51 +00:00
MEMORYBARRIER ( isp , SYNC_SFORDEV , 0 , sizeof ( * icbp ) , 0 ) ;
2006-11-02 03:21:32 +00:00
isp_mboxcmd ( isp , & mbs ) ;
2009-08-01 01:04:26 +00:00
FC_SCRATCH_RELEASE ( isp , 0 ) ;
2006-11-02 03:21:32 +00:00
if ( mbs . param [ 0 ] ! = MBOX_COMMAND_COMPLETE ) {
return ;
}
/*
* Whatever happens , we ' re now committed to being here .
*/
2015-10-25 10:49:05 +00:00
isp - > isp_state = ISP_RUNSTATE ;
2006-11-02 03:21:32 +00:00
}
2015-12-25 03:44:29 +00:00
static int
isp_fc_enable_vp ( ispsoftc_t * isp , int chan )
{
fcparam * fcp = FCPARAM ( isp , chan ) ;
2015-12-26 04:26:32 +00:00
vp_modify_t vp ;
2020-11-27 15:50:20 +00:00
int retval ;
2015-12-25 03:44:29 +00:00
/* Build a VP MODIFY command in memory */
2015-12-26 04:26:32 +00:00
ISP_MEMZERO ( & vp , sizeof ( vp ) ) ;
vp . vp_mod_hdr . rqs_entry_type = RQSTYPE_VP_MODIFY ;
vp . vp_mod_hdr . rqs_entry_count = 1 ;
vp . vp_mod_cnt = 1 ;
vp . vp_mod_idx0 = chan ;
vp . vp_mod_cmd = VP_MODIFY_ENA ;
vp . vp_mod_ports [ 0 ] . options = ICB2400_VPOPT_ENABLED |
2015-12-25 03:44:29 +00:00
ICB2400_VPOPT_ENA_SNSLOGIN ;
2015-12-26 04:26:32 +00:00
if ( fcp - > role & ISP_ROLE_INITIATOR )
vp . vp_mod_ports [ 0 ] . options | = ICB2400_VPOPT_INI_ENABLE ;
if ( ( fcp - > role & ISP_ROLE_TARGET ) = = 0 )
vp . vp_mod_ports [ 0 ] . options | = ICB2400_VPOPT_TGT_DISABLE ;
2015-12-25 03:44:29 +00:00
if ( fcp - > isp_loopid < LOCAL_LOOP_LIM ) {
2015-12-26 04:26:32 +00:00
vp . vp_mod_ports [ 0 ] . loopid = fcp - > isp_loopid ;
2015-12-25 03:44:29 +00:00
if ( isp - > isp_confopts & ISP_CFG_OWNLOOPID )
2015-12-26 04:26:32 +00:00
vp . vp_mod_ports [ 0 ] . options | = ICB2400_VPOPT_HARD_ADDRESS ;
2015-12-25 03:44:29 +00:00
}
2015-12-26 04:26:32 +00:00
MAKE_NODE_NAME_FROM_WWN ( vp . vp_mod_ports [ 0 ] . wwpn , fcp - > isp_wwpn ) ;
MAKE_NODE_NAME_FROM_WWN ( vp . vp_mod_ports [ 0 ] . wwnn , fcp - > isp_wwnn ) ;
2015-12-25 03:44:29 +00:00
2020-11-27 15:50:20 +00:00
retval = isp_exec_entry_queue ( isp , & vp , & vp , 5 ) ;
if ( retval ! = 0 ) {
isp_prt ( isp , ISP_LOGERR , " %s: VP_MODIFY of chan %d error %d " ,
__func__ , chan , retval ) ;
return ( retval ) ;
2015-12-26 04:26:32 +00:00
}
2015-12-25 03:44:29 +00:00
2015-12-26 04:26:32 +00:00
if ( vp . vp_mod_hdr . rqs_flags ! = 0 | | vp . vp_mod_status ! = VP_STS_OK ) {
isp_prt ( isp , ISP_LOGERR ,
" %s: VP_MODIFY of Chan %d failed with flags %x status %d " ,
__func__ , chan , vp . vp_mod_hdr . rqs_flags , vp . vp_mod_status ) ;
2015-12-25 03:44:29 +00:00
return ( EIO ) ;
}
return ( 0 ) ;
}
static int
isp_fc_disable_vp ( ispsoftc_t * isp , int chan )
{
2015-12-26 04:26:32 +00:00
vp_ctrl_info_t vp ;
2020-11-27 15:50:20 +00:00
int retval ;
2015-12-25 03:44:29 +00:00
/* Build a VP CTRL command in memory */
2015-12-26 04:26:32 +00:00
ISP_MEMZERO ( & vp , sizeof ( vp ) ) ;
vp . vp_ctrl_hdr . rqs_entry_type = RQSTYPE_VP_CTRL ;
vp . vp_ctrl_hdr . rqs_entry_count = 1 ;
2015-12-25 03:44:29 +00:00
if ( ISP_CAP_VP0 ( isp ) ) {
2015-12-26 04:26:32 +00:00
vp . vp_ctrl_status = 1 ;
2015-12-25 03:44:29 +00:00
} else {
2015-12-26 04:26:32 +00:00
vp . vp_ctrl_status = 0 ;
2015-12-25 03:44:29 +00:00
chan - - ; /* VP0 can not be controlled in this case. */
}
2015-12-26 04:26:32 +00:00
vp . vp_ctrl_command = VP_CTRL_CMD_DISABLE_VP_LOGO_ALL ;
vp . vp_ctrl_vp_count = 1 ;
vp . vp_ctrl_idmap [ chan / 16 ] | = ( 1 < < chan % 16 ) ;
2015-12-25 03:44:29 +00:00
2020-11-27 15:50:20 +00:00
retval = isp_exec_entry_queue ( isp , & vp , & vp , 5 ) ;
if ( retval ! = 0 ) {
isp_prt ( isp , ISP_LOGERR , " %s: VP_CTRL of chan %d error %d " ,
__func__ , chan , retval ) ;
return ( retval ) ;
2015-12-26 04:26:32 +00:00
}
2015-12-25 03:44:29 +00:00
2015-12-26 04:26:32 +00:00
if ( vp . vp_ctrl_hdr . rqs_flags ! = 0 | | vp . vp_ctrl_status ! = 0 ) {
2015-12-25 03:44:29 +00:00
isp_prt ( isp , ISP_LOGERR ,
2015-12-26 04:26:32 +00:00
" %s: VP_CTRL of Chan %d failed with flags %x status %d %d " ,
__func__ , chan , vp . vp_ctrl_hdr . rqs_flags ,
vp . vp_ctrl_status , vp . vp_ctrl_index_fail ) ;
2015-12-25 03:44:29 +00:00
return ( EIO ) ;
}
return ( 0 ) ;
}
static int
isp_fc_change_role ( ispsoftc_t * isp , int chan , int new_role )
{
fcparam * fcp = FCPARAM ( isp , chan ) ;
int i , was , res = 0 ;
if ( chan > = isp - > isp_nchan ) {
isp_prt ( isp , ISP_LOGWARN , " %s: bad channel %d " , __func__ , chan ) ;
return ( ENXIO ) ;
}
if ( fcp - > role = = new_role )
return ( 0 ) ;
for ( was = 0 , i = 0 ; i < isp - > isp_nchan ; i + + ) {
if ( FCPARAM ( isp , i ) - > role ! = ISP_ROLE_NONE )
was + + ;
}
if ( was = = 0 | | ( was = = 1 & & fcp - > role ! = ISP_ROLE_NONE ) ) {
fcp - > role = new_role ;
return ( isp_reinit ( isp , 0 ) ) ;
}
if ( fcp - > role ! = ISP_ROLE_NONE ) {
res = isp_fc_disable_vp ( isp , chan ) ;
isp_clear_portdb ( isp , chan ) ;
}
fcp - > role = new_role ;
if ( fcp - > role ! = ISP_ROLE_NONE )
res = isp_fc_enable_vp ( isp , chan ) ;
return ( res ) ;
}
2006-11-02 03:21:32 +00:00
static void
2015-11-19 17:43:47 +00:00
isp_clear_portdb ( ispsoftc_t * isp , int chan )
2006-11-02 03:21:32 +00:00
{
2009-08-01 01:04:26 +00:00
fcparam * fcp = FCPARAM ( isp , chan ) ;
2015-07-13 15:11:05 +00:00
fcportdb_t * lp ;
2006-11-02 03:21:32 +00:00
int i ;
for ( i = 0 ; i < MAX_FC_TARG ; i + + ) {
2015-07-13 15:11:05 +00:00
lp = & fcp - > portdb [ i ] ;
switch ( lp - > state ) {
case FC_PORTDB_STATE_DEAD :
case FC_PORTDB_STATE_CHANGED :
case FC_PORTDB_STATE_VALID :
2015-11-19 17:43:47 +00:00
lp - > state = FC_PORTDB_STATE_NIL ;
isp_async ( isp , ISPASYNC_DEV_GONE , chan , lp ) ;
2015-07-13 15:11:05 +00:00
break ;
case FC_PORTDB_STATE_NIL :
case FC_PORTDB_STATE_NEW :
lp - > state = FC_PORTDB_STATE_NIL ;
break ;
2015-11-19 17:43:47 +00:00
case FC_PORTDB_STATE_ZOMBIE :
break ;
default :
panic ( " Don't know how to clear state %d \n " , lp - > state ) ;
2006-11-02 03:21:32 +00:00
}
}
}
2015-11-19 17:43:47 +00:00
static void
isp_mark_portdb ( ispsoftc_t * isp , int chan )
{
fcparam * fcp = FCPARAM ( isp , chan ) ;
fcportdb_t * lp ;
int i ;
for ( i = 0 ; i < MAX_FC_TARG ; i + + ) {
lp = & fcp - > portdb [ i ] ;
if ( lp - > state = = FC_PORTDB_STATE_NIL )
continue ;
2015-11-21 21:01:00 +00:00
if ( lp - > portid > = DOMAIN_CONTROLLER_BASE & &
lp - > portid < = DOMAIN_CONTROLLER_END )
2015-11-19 17:43:47 +00:00
continue ;
fcp - > portdb [ i ] . probational = 1 ;
}
}
2006-11-02 03:21:32 +00:00
/*
* Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24 XX cards
2006-11-18 03:53:16 +00:00
* or via FABRIC LOGIN / FABRIC LOGOUT for other cards .
2006-11-02 03:21:32 +00:00
*/
2006-11-18 03:53:16 +00:00
static int
2015-12-26 06:13:01 +00:00
isp_plogx ( ispsoftc_t * isp , int chan , uint16_t handle , uint32_t portid , int flags )
2006-11-02 03:21:32 +00:00
{
2015-12-26 06:13:01 +00:00
isp_plogx_t pl ;
2006-11-02 03:21:32 +00:00
uint32_t sst , parm1 ;
2020-11-27 15:50:20 +00:00
int retval , lev ;
2009-08-01 01:04:26 +00:00
const char * msg ;
char buf [ 64 ] ;
2006-11-18 03:53:16 +00:00
2015-11-19 17:43:47 +00:00
isp_prt ( isp , ISP_LOG_SANCFG , " Chan %d PLOGX %s PortID 0x%06x nphdl 0x%x " ,
chan , ( flags & PLOGX_FLG_CMD_MASK ) = = PLOGX_FLG_CMD_PLOGI ?
" Login " : " Logout " , portid , handle ) ;
2006-11-02 03:21:32 +00:00
2015-12-26 06:13:01 +00:00
ISP_MEMZERO ( & pl , sizeof ( pl ) ) ;
pl . plogx_header . rqs_entry_count = 1 ;
pl . plogx_header . rqs_entry_type = RQSTYPE_LOGIN ;
pl . plogx_nphdl = handle ;
pl . plogx_vphdl = chan ;
pl . plogx_portlo = portid ;
pl . plogx_rspsz_porthi = ( portid > > 16 ) & 0xff ;
pl . plogx_flags = flags ;
2006-11-02 03:21:32 +00:00
2020-11-27 15:50:20 +00:00
retval = isp_exec_entry_queue ( isp , & pl , & pl , 3 * ICB_LOGIN_TOV ) ;
if ( retval ! = 0 ) {
isp_prt ( isp , ISP_LOGERR , " %s: PLOGX of chan %d error %d " ,
__func__ , chan , retval ) ;
return ( retval ) ;
2006-11-02 03:21:32 +00:00
}
2015-12-26 06:13:01 +00:00
if ( pl . plogx_status = = PLOGX_STATUS_OK ) {
return ( 0 ) ;
} else if ( pl . plogx_status ! = PLOGX_STATUS_IOCBERR ) {
2009-08-01 01:04:26 +00:00
isp_prt ( isp , ISP_LOGWARN ,
2012-07-15 14:40:49 +00:00
" status 0x%x on port login IOCB channel %d " ,
2015-12-26 06:13:01 +00:00
pl . plogx_status , chan ) ;
return ( - 1 ) ;
2006-11-02 03:21:32 +00:00
}
2015-12-26 06:13:01 +00:00
sst = pl . plogx_ioparm [ 0 ] . lo16 | ( pl . plogx_ioparm [ 0 ] . hi16 < < 16 ) ;
parm1 = pl . plogx_ioparm [ 1 ] . lo16 | ( pl . plogx_ioparm [ 1 ] . hi16 < < 16 ) ;
2006-11-02 03:21:32 +00:00
2020-11-27 15:50:20 +00:00
retval = - 1 ;
2009-08-01 01:04:26 +00:00
lev = ISP_LOGERR ;
msg = NULL ;
2006-11-02 03:21:32 +00:00
switch ( sst ) {
case PLOGX_IOCBERR_NOLINK :
2009-08-01 01:04:26 +00:00
msg = " no link " ;
2006-11-02 03:21:32 +00:00
break ;
case PLOGX_IOCBERR_NOIOCB :
2009-08-01 01:04:26 +00:00
msg = " no IOCB buffer " ;
2006-11-02 03:21:32 +00:00
break ;
case PLOGX_IOCBERR_NOXGHG :
2009-08-01 01:04:26 +00:00
msg = " no Exchange Control Block " ;
2006-11-02 03:21:32 +00:00
break ;
case PLOGX_IOCBERR_FAILED :
2010-02-18 18:35:09 +00:00
ISP_SNPRINTF ( buf , sizeof ( buf ) , " reason 0x%x (last LOGIN state 0x%x) " , parm1 & 0xff , ( parm1 > > 8 ) & 0xff ) ;
2009-08-01 01:04:26 +00:00
msg = buf ;
2006-11-02 03:21:32 +00:00
break ;
case PLOGX_IOCBERR_NOFABRIC :
2009-08-01 01:04:26 +00:00
msg = " no fabric " ;
2006-11-02 03:21:32 +00:00
break ;
case PLOGX_IOCBERR_NOTREADY :
2009-08-01 01:04:26 +00:00
msg = " firmware not ready " ;
2006-11-02 03:21:32 +00:00
break ;
case PLOGX_IOCBERR_NOLOGIN :
2010-02-18 18:35:09 +00:00
ISP_SNPRINTF ( buf , sizeof ( buf ) , " not logged in (last state 0x%x) " , parm1 ) ;
2009-08-01 01:04:26 +00:00
msg = buf ;
2020-11-27 15:50:20 +00:00
retval = MBOX_NOT_LOGGED_IN ;
2006-11-02 03:21:32 +00:00
break ;
case PLOGX_IOCBERR_REJECT :
2009-08-01 01:04:26 +00:00
ISP_SNPRINTF ( buf , sizeof ( buf ) , " LS_RJT = 0x%x " , parm1 ) ;
msg = buf ;
2006-11-02 03:21:32 +00:00
break ;
case PLOGX_IOCBERR_NOPCB :
2009-08-01 01:04:26 +00:00
msg = " no PCB allocated " ;
2006-11-02 03:21:32 +00:00
break ;
case PLOGX_IOCBERR_EINVAL :
2010-02-18 18:35:09 +00:00
ISP_SNPRINTF ( buf , sizeof ( buf ) , " invalid parameter at offset 0x%x " , parm1 ) ;
2009-08-01 01:04:26 +00:00
msg = buf ;
2006-11-02 03:21:32 +00:00
break ;
case PLOGX_IOCBERR_PORTUSED :
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
lev = ISP_LOG_SANCFG | ISP_LOG_WARN1 ;
2010-02-18 18:35:09 +00:00
ISP_SNPRINTF ( buf , sizeof ( buf ) , " already logged in with N-Port handle 0x%x " , parm1 ) ;
2009-08-01 01:04:26 +00:00
msg = buf ;
2020-11-27 15:50:20 +00:00
retval = MBOX_PORT_ID_USED | ( parm1 < < 16 ) ;
2006-11-02 03:21:32 +00:00
break ;
case PLOGX_IOCBERR_HNDLUSED :
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
lev = ISP_LOG_SANCFG | ISP_LOG_WARN1 ;
2010-02-18 18:35:09 +00:00
ISP_SNPRINTF ( buf , sizeof ( buf ) , " handle already used for PortID 0x%06x " , parm1 ) ;
2009-08-01 01:04:26 +00:00
msg = buf ;
2020-11-27 15:50:20 +00:00
retval = MBOX_LOOP_ID_USED ;
2006-11-02 03:21:32 +00:00
break ;
case PLOGX_IOCBERR_NOHANDLE :
2009-08-01 01:04:26 +00:00
msg = " no handle allocated " ;
2006-11-02 03:21:32 +00:00
break ;
case PLOGX_IOCBERR_NOFLOGI :
2009-08-01 01:04:26 +00:00
msg = " no FLOGI_ACC " ;
2006-11-02 03:21:32 +00:00
break ;
default :
2015-12-26 06:13:01 +00:00
ISP_SNPRINTF ( buf , sizeof ( buf ) , " status %x from %x " , pl . plogx_status , flags ) ;
2009-08-01 01:04:26 +00:00
msg = buf ;
2006-11-02 03:21:32 +00:00
break ;
1999-03-17 05:04:39 +00:00
}
2009-08-01 01:04:26 +00:00
if ( msg ) {
2017-04-09 07:53:31 +00:00
isp_prt ( isp , lev , " Chan %d PLOGX PortID 0x%06x to N-Port handle 0x%x: %s " ,
chan , portid , handle , msg ) ;
2009-08-01 01:04:26 +00:00
}
2020-11-27 15:50:20 +00:00
return ( retval ) ;
1999-03-17 05:04:39 +00:00
}
2006-11-02 03:21:32 +00:00
static int
2015-12-27 06:28:31 +00:00
isp_getpdb ( ispsoftc_t * isp , int chan , uint16_t id , isp_pdb_t * pdb )
1999-03-17 05:04:39 +00:00
{
mbreg_t mbs ;
2006-11-02 03:21:32 +00:00
union {
isp_pdb_24xx_t bill ;
} un ;
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
2015-10-29 16:48:12 +00:00
MBSINIT ( & mbs , MBOX_GET_PORT_DB ,
MBLOGALL & ~ MBLOGMASK ( MBOX_COMMAND_PARAM_ERROR ) , 250000 ) ;
2020-11-20 01:15:48 +00:00
mbs . ibits = ( 1 < < 9 ) | ( 1 < < 10 ) ;
mbs . param [ 1 ] = id ;
2016-04-12 14:43:17 +00:00
mbs . param [ 2 ] = DMA_WD1 ( isp - > isp_iocb_dma ) ;
mbs . param [ 3 ] = DMA_WD0 ( isp - > isp_iocb_dma ) ;
mbs . param [ 6 ] = DMA_WD3 ( isp - > isp_iocb_dma ) ;
mbs . param [ 7 ] = DMA_WD2 ( isp - > isp_iocb_dma ) ;
2020-11-20 01:15:48 +00:00
mbs . param [ 9 ] = chan ;
2016-04-12 14:43:17 +00:00
MEMORYBARRIER ( isp , SYNC_IFORDEV , 0 , sizeof ( un ) , chan ) ;
2006-11-02 03:21:32 +00:00
isp_mboxcmd ( isp , & mbs ) ;
2016-04-12 14:43:17 +00:00
if ( mbs . param [ 0 ] ! = MBOX_COMMAND_COMPLETE )
2015-10-28 12:34:59 +00:00
return ( mbs . param [ 0 ] | ( mbs . param [ 1 ] < < 16 ) ) ;
2016-04-12 14:43:17 +00:00
MEMORYBARRIER ( isp , SYNC_IFORCPU , 0 , sizeof ( un ) , chan ) ;
2020-11-20 01:15:48 +00:00
isp_get_pdb_24xx ( isp , isp - > isp_iocb , & un . bill ) ;
pdb - > handle = un . bill . pdb_handle ;
pdb - > prli_word0 = un . bill . pdb_prli_svc0 ;
pdb - > prli_word3 = un . bill . pdb_prli_svc3 ;
pdb - > portid = BITS2WORD_24XX ( un . bill . pdb_portid_bits ) ;
ISP_MEMCPY ( pdb - > portname , un . bill . pdb_portname , 8 ) ;
ISP_MEMCPY ( pdb - > nodename , un . bill . pdb_nodename , 8 ) ;
isp_prt ( isp , ISP_LOGDEBUG0 ,
" Chan %d handle 0x%x Port 0x%06x flags 0x%x curstate %x laststate %x " ,
chan , id , pdb - > portid , un . bill . pdb_flags ,
un . bill . pdb_curstate , un . bill . pdb_laststate ) ;
if ( un . bill . pdb_curstate < PDB2400_STATE_PLOGI_DONE | | un . bill . pdb_curstate > PDB2400_STATE_LOGGED_IN ) {
mbs . param [ 0 ] = MBOX_NOT_LOGGED_IN ;
return ( mbs . param [ 0 ] ) ;
2006-11-02 03:21:32 +00:00
}
return ( 0 ) ;
1999-03-17 05:04:39 +00:00
}
2015-10-28 12:34:59 +00:00
static int
2015-12-27 06:28:31 +00:00
isp_gethandles ( ispsoftc_t * isp , int chan , uint16_t * handles , int * num , int loop )
2015-10-28 12:34:59 +00:00
{
fcparam * fcp = FCPARAM ( isp , chan ) ;
mbreg_t mbs ;
isp_pnhle_24xx_t el4 , * elp4 ;
int i , j ;
uint32_t p ;
2015-10-29 16:48:12 +00:00
MBSINIT ( & mbs , MBOX_GET_ID_LIST , MBLOGALL , 250000 ) ;
2020-11-20 01:15:48 +00:00
mbs . param [ 2 ] = DMA_WD1 ( fcp - > isp_scdma ) ;
mbs . param [ 3 ] = DMA_WD0 ( fcp - > isp_scdma ) ;
mbs . param [ 6 ] = DMA_WD3 ( fcp - > isp_scdma ) ;
mbs . param [ 7 ] = DMA_WD2 ( fcp - > isp_scdma ) ;
mbs . param [ 8 ] = ISP_FC_SCRLEN ;
mbs . param [ 9 ] = chan ;
2015-12-27 06:28:31 +00:00
if ( FC_SCRATCH_ACQUIRE ( isp , chan ) ) {
isp_prt ( isp , ISP_LOGERR , sacq ) ;
return ( - 1 ) ;
2015-10-28 12:34:59 +00:00
}
MEMORYBARRIER ( isp , SYNC_SFORDEV , 0 , ISP_FC_SCRLEN , chan ) ;
isp_mboxcmd ( isp , & mbs ) ;
if ( mbs . param [ 0 ] ! = MBOX_COMMAND_COMPLETE ) {
2015-12-27 06:28:31 +00:00
FC_SCRATCH_RELEASE ( isp , chan ) ;
2015-10-28 12:34:59 +00:00
return ( mbs . param [ 0 ] | ( mbs . param [ 1 ] < < 16 ) ) ;
}
2016-04-12 11:48:50 +00:00
MEMORYBARRIER ( isp , SYNC_SFORCPU , 0 , ISP_FC_SCRLEN , chan ) ;
2015-10-28 12:34:59 +00:00
elp4 = fcp - > isp_scratch ;
for ( i = 0 , j = 0 ; i < mbs . param [ 1 ] & & j < * num ; i + + ) {
2020-11-20 01:15:48 +00:00
isp_get_pnhle_24xx ( isp , & elp4 [ i ] , & el4 ) ;
p = el4 . pnhle_port_id_lo | ( el4 . pnhle_port_id_hi < < 16 ) ;
2015-10-28 12:34:59 +00:00
if ( loop & & ( p > > 8 ) ! = ( fcp - > isp_portid > > 8 ) )
continue ;
2020-11-20 01:15:48 +00:00
handles [ j + + ] = el4 . pnhle_handle ;
2015-10-28 12:34:59 +00:00
}
* num = j ;
2015-12-27 06:28:31 +00:00
FC_SCRATCH_RELEASE ( isp , chan ) ;
2015-10-28 12:34:59 +00:00
return ( 0 ) ;
}
2009-08-01 01:04:26 +00:00
static void
2015-12-27 06:28:31 +00:00
isp_dump_chip_portdb ( ispsoftc_t * isp , int chan )
2009-08-01 01:04:26 +00:00
{
isp_pdb_t pdb ;
2020-11-20 01:15:48 +00:00
uint16_t nphdl ;
2009-08-01 01:04:26 +00:00
2015-07-13 15:11:05 +00:00
isp_prt ( isp , ISP_LOG_SANCFG | ISP_LOGINFO , " Chan %d chip port dump " , chan ) ;
2020-11-20 01:15:48 +00:00
for ( nphdl = 0 ; nphdl ! = NPH_MAX_2K ; nphdl + + ) {
2015-12-27 06:28:31 +00:00
if ( isp_getpdb ( isp , chan , nphdl , & pdb ) ) {
2009-08-01 01:04:26 +00:00
continue ;
}
2015-11-18 11:14:59 +00:00
isp_prt ( isp , ISP_LOG_SANCFG | ISP_LOGINFO , " Chan %d Handle 0x%04x "
2009-08-01 01:04:26 +00:00
" PortID 0x%06x WWPN 0x%02x%02x%02x%02x%02x%02x%02x%02x " ,
2015-11-18 11:14:59 +00:00
chan , nphdl , pdb . portid , pdb . portname [ 0 ] , pdb . portname [ 1 ] ,
2009-08-01 01:04:26 +00:00
pdb . portname [ 2 ] , pdb . portname [ 3 ] , pdb . portname [ 4 ] ,
pdb . portname [ 5 ] , pdb . portname [ 6 ] , pdb . portname [ 7 ] ) ;
}
}
2006-02-15 00:31:48 +00:00
static uint64_t
2015-11-18 11:14:59 +00:00
isp_get_wwn ( ispsoftc_t * isp , int chan , int nphdl , int nodename )
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
{
2009-08-01 01:04:26 +00:00
uint64_t wwn = INI_NONE ;
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
mbreg_t mbs ;
2015-10-29 16:48:12 +00:00
MBSINIT ( & mbs , MBOX_GET_PORT_NAME ,
MBLOGALL & ~ MBLOGMASK ( MBOX_COMMAND_PARAM_ERROR ) , 500000 ) ;
2020-11-20 01:15:48 +00:00
mbs . param [ 1 ] = nphdl ;
if ( nodename )
mbs . param [ 10 ] = 1 ;
mbs . param [ 9 ] = chan ;
2006-11-02 03:21:32 +00:00
isp_mboxcmd ( isp , & mbs ) ;
if ( mbs . param [ 0 ] ! = MBOX_COMMAND_COMPLETE ) {
return ( wwn ) ;
}
2020-11-20 01:15:48 +00:00
wwn = ( ( ( uint64_t ) ( mbs . param [ 2 ] > > 8 ) ) < < 56 ) |
( ( ( uint64_t ) ( mbs . param [ 2 ] & 0xff ) ) < < 48 ) |
( ( ( uint64_t ) ( mbs . param [ 3 ] > > 8 ) ) < < 40 ) |
( ( ( uint64_t ) ( mbs . param [ 3 ] & 0xff ) ) < < 32 ) |
( ( ( uint64_t ) ( mbs . param [ 6 ] > > 8 ) ) < < 24 ) |
( ( ( uint64_t ) ( mbs . param [ 6 ] & 0xff ) ) < < 16 ) |
( ( ( uint64_t ) ( mbs . param [ 7 ] > > 8 ) ) < < 8 ) |
( ( ( uint64_t ) ( mbs . param [ 7 ] & 0xff ) ) ) ;
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
return ( wwn ) ;
}
1999-03-17 05:04:39 +00:00
/*
2006-11-02 03:21:32 +00:00
* Make sure we have good FC link .
1999-03-17 05:04:39 +00:00
*/
static int
2009-08-01 01:04:26 +00:00
isp_fclink_test ( ispsoftc_t * isp , int chan , int usdelay )
1999-03-17 05:04:39 +00:00
{
mbreg_t mbs ;
2020-11-20 01:15:48 +00:00
int i , r , topo ;
1999-03-17 05:04:39 +00:00
fcparam * fcp ;
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
isp_pdb_t pdb ;
2015-11-07 18:26:02 +00:00
NANOTIME_T hra , hrb ;
2001-02-11 03:44:43 +00:00
2009-08-01 01:04:26 +00:00
fcp = FCPARAM ( isp , chan ) ;
1999-03-17 05:04:39 +00:00
2015-11-26 13:04:58 +00:00
if ( fcp - > isp_loopstate < LOOP_HAVE_LINK )
return ( - 1 ) ;
2015-11-17 16:33:46 +00:00
if ( fcp - > isp_loopstate > = LOOP_LTEST_DONE )
return ( 0 ) ;
isp_prt ( isp , ISP_LOG_SANCFG , " Chan %d FC link test " , chan ) ;
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
1999-03-17 05:04:39 +00:00
/*
* Wait up to N microseconds for F / W to go to a ready state .
1998-04-22 17:54:58 +00:00
*/
2015-11-07 18:26:02 +00:00
GET_NANOTIME ( & hra ) ;
2015-11-07 19:33:57 +00:00
while ( 1 ) {
2015-11-17 16:33:46 +00:00
isp_change_fw_state ( isp , chan , isp_fw_state ( isp , chan ) ) ;
1998-04-22 17:54:58 +00:00
if ( fcp - > isp_fwstate = = FW_READY ) {
break ;
}
2016-04-14 20:49:01 +00:00
if ( fcp - > isp_loopstate < LOOP_HAVE_LINK )
2015-11-26 13:04:58 +00:00
goto abort ;
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
GET_NANOTIME ( & hrb ) ;
2015-11-07 19:33:57 +00:00
if ( ( NANOTIME_SUB ( & hrb , & hra ) / 1000 + 1000 > = usdelay ) )
break ;
ISP_SLEEP ( isp , 1000 ) ;
}
1999-03-17 05:04:39 +00:00
if ( fcp - > isp_fwstate ! = FW_READY ) {
2015-11-17 16:46:05 +00:00
isp_prt ( isp , ISP_LOG_SANCFG ,
" Chan %d Firmware is not ready (%s) " ,
chan , isp_fc_fw_statename ( fcp - > isp_fwstate ) ) ;
1999-03-17 05:04:39 +00:00
return ( - 1 ) ;
1998-04-22 17:54:58 +00:00
}
1999-03-25 22:52:45 +00:00
1999-03-17 05:04:39 +00:00
/*
2006-11-02 03:21:32 +00:00
* Get our Loop ID and Port ID .
1999-03-17 05:04:39 +00:00
*/
2009-08-01 01:04:26 +00:00
MBSINIT ( & mbs , MBOX_GET_LOOP_ID , MBLOGALL , 0 ) ;
2012-06-17 21:39:40 +00:00
mbs . param [ 9 ] = chan ;
2006-11-02 03:21:32 +00:00
isp_mboxcmd ( isp , & mbs ) ;
1999-03-17 05:04:39 +00:00
if ( mbs . param [ 0 ] ! = MBOX_COMMAND_COMPLETE ) {
return ( - 1 ) ;
}
2006-11-02 03:21:32 +00:00
2020-11-20 01:15:48 +00:00
topo = ( int ) mbs . param [ 6 ] ;
if ( topo < TOPO_NL_PORT | | topo > TOPO_PTP_STUB )
topo = TOPO_PTP_STUB ;
fcp - > isp_topo = topo ;
2006-02-02 09:02:16 +00:00
fcp - > isp_portid = mbs . param [ 2 ] | ( mbs . param [ 3 ] < < 16 ) ;
2000-05-09 01:14:43 +00:00
2015-11-19 17:43:47 +00:00
if ( ! TOPO_IS_FABRIC ( fcp - > isp_topo ) ) {
fcp - > isp_loopid = mbs . param [ 1 ] & 0xff ;
} else if ( fcp - > isp_topo ! = TOPO_F_PORT ) {
2009-08-01 01:04:26 +00:00
uint8_t alpa = fcp - > isp_portid ;
2015-11-19 17:43:47 +00:00
for ( i = 0 ; alpa_map [ i ] ; i + + ) {
if ( alpa_map [ i ] = = alpa )
break ;
2009-08-01 01:04:26 +00:00
}
2015-11-19 17:43:47 +00:00
if ( alpa_map [ i ] )
fcp - > isp_loopid = i ;
2009-08-01 01:04:26 +00:00
}
2016-04-14 20:49:01 +00:00
#if 0
fcp - > isp_loopstate = LOOP_HAVE_ADDR ;
# endif
fcp - > isp_loopstate = LOOP_TESTING_LINK ;
2015-11-18 12:39:20 +00:00
if ( fcp - > isp_topo = = TOPO_F_PORT | | fcp - > isp_topo = = TOPO_FL_PORT ) {
2020-11-20 01:15:48 +00:00
r = isp_getpdb ( isp , chan , NPH_FL_ID , & pdb ) ;
2015-11-18 12:39:20 +00:00
if ( r ! = 0 | | pdb . portid = = 0 ) {
2020-11-20 01:15:48 +00:00
isp_prt ( isp , ISP_LOGWARN ,
" fabric topology, but cannot get info about fabric controller (0x%x) " , r ) ;
fcp - > isp_topo = TOPO_PTP_STUB ;
2001-02-11 03:44:43 +00:00
goto not_on_fabric ;
}
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
2020-11-20 01:15:48 +00:00
fcp - > isp_fabric_params = mbs . param [ 7 ] ;
fcp - > isp_sns_hdl = NPH_SNS_ID ;
r = isp_register_fc4_type ( isp , chan ) ;
if ( fcp - > isp_loopstate < LOOP_TESTING_LINK )
goto abort ;
if ( r ! = 0 )
goto not_on_fabric ;
r = isp_register_fc4_features_24xx ( isp , chan ) ;
if ( fcp - > isp_loopstate < LOOP_TESTING_LINK )
goto abort ;
if ( r ! = 0 )
goto not_on_fabric ;
r = isp_register_port_name_24xx ( isp , chan ) ;
if ( fcp - > isp_loopstate < LOOP_TESTING_LINK )
goto abort ;
if ( r ! = 0 )
goto not_on_fabric ;
isp_register_node_name_24xx ( isp , chan ) ;
if ( fcp - > isp_loopstate < LOOP_TESTING_LINK )
goto abort ;
2000-05-09 01:14:43 +00:00
}
2015-11-18 12:39:20 +00:00
not_on_fabric :
2015-11-19 17:43:47 +00:00
/* Get link speed. */
2001-10-01 03:45:54 +00:00
fcp - > isp_gbspeed = 1 ;
2020-11-20 01:15:48 +00:00
MBSINIT ( & mbs , MBOX_GET_SET_DATA_RATE , MBLOGALL , 3000000 ) ;
mbs . param [ 1 ] = MBGSD_GET_RATE ;
/* mbs.param[2] undefined if we're just getting rate */
isp_mboxcmd ( isp , & mbs ) ;
if ( mbs . param [ 0 ] = = MBOX_COMMAND_COMPLETE ) {
if ( mbs . param [ 1 ] = = MBGSD_10GB )
fcp - > isp_gbspeed = 10 ;
else if ( mbs . param [ 1 ] = = MBGSD_32GB )
fcp - > isp_gbspeed = 32 ;
else if ( mbs . param [ 1 ] = = MBGSD_16GB )
fcp - > isp_gbspeed = 16 ;
else if ( mbs . param [ 1 ] = = MBGSD_8GB )
fcp - > isp_gbspeed = 8 ;
else if ( mbs . param [ 1 ] = = MBGSD_4GB )
fcp - > isp_gbspeed = 4 ;
else if ( mbs . param [ 1 ] = = MBGSD_2GB )
fcp - > isp_gbspeed = 2 ;
else if ( mbs . param [ 1 ] = = MBGSD_1GB )
fcp - > isp_gbspeed = 1 ;
2001-10-01 03:45:54 +00:00
}
2015-11-26 13:04:58 +00:00
if ( fcp - > isp_loopstate < LOOP_TESTING_LINK ) {
abort :
isp_prt ( isp , ISP_LOG_SANCFG ,
" Chan %d FC link test aborted " , chan ) ;
return ( 1 ) ;
}
2015-11-17 16:33:46 +00:00
fcp - > isp_loopstate = LOOP_LTEST_DONE ;
2015-11-19 17:43:47 +00:00
isp_prt ( isp , ISP_LOG_SANCFG | ISP_LOGCONFIG ,
" Chan %d WWPN %016jx WWNN %016jx " ,
chan , ( uintmax_t ) fcp - > isp_wwpn , ( uintmax_t ) fcp - > isp_wwnn ) ;
isp_prt ( isp , ISP_LOG_SANCFG | ISP_LOGCONFIG ,
" Chan %d %dGb %s PortID 0x%06x LoopID 0x%02x " ,
chan , fcp - > isp_gbspeed , isp_fc_toponame ( fcp ) , fcp - > isp_portid ,
fcp - > isp_loopid ) ;
2015-11-17 16:33:46 +00:00
isp_prt ( isp , ISP_LOG_SANCFG , " Chan %d FC link test done " , chan ) ;
1999-03-17 05:04:39 +00:00
return ( 0 ) ;
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
}
/*
2006-11-02 03:21:32 +00:00
* Complete the synchronization of our Port Database .
*
* At this point , we ' ve scanned the local loop ( if any ) and the fabric
* and performed fabric logins on all new devices .
*
2015-11-17 16:33:46 +00:00
* Our task here is to go through our port database removing any entities
2006-11-02 03:21:32 +00:00
* that are still marked probational ( issuing PLOGO for ones which we had
2015-11-17 16:33:46 +00:00
* PLOGI ' d into ) or are dead , and notifying upper layers about new / changed
* devices .
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
*/
static int
2009-08-01 01:04:26 +00:00
isp_pdb_sync ( ispsoftc_t * isp , int chan )
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
{
2009-08-01 01:04:26 +00:00
fcparam * fcp = FCPARAM ( isp , chan ) ;
2006-11-02 03:21:32 +00:00
fcportdb_t * lp ;
uint16_t dbidx ;
2015-11-26 13:04:58 +00:00
if ( fcp - > isp_loopstate < LOOP_FSCAN_DONE )
2001-02-11 03:44:43 +00:00
return ( - 1 ) ;
2015-11-26 13:04:58 +00:00
if ( fcp - > isp_loopstate > = LOOP_READY )
2015-11-17 16:33:46 +00:00
return ( 0 ) ;
2001-02-11 03:44:43 +00:00
2015-11-17 16:33:46 +00:00
isp_prt ( isp , ISP_LOG_SANCFG , " Chan %d FC PDB sync " , chan ) ;
2006-11-14 08:45:48 +00:00
2006-11-02 03:21:32 +00:00
fcp - > isp_loopstate = LOOP_SYNCING_PDB ;
2001-02-11 03:44:43 +00:00
2006-11-02 03:21:32 +00:00
for ( dbidx = 0 ; dbidx < MAX_FC_TARG ; dbidx + + ) {
lp = & fcp - > portdb [ dbidx ] ;
2001-02-11 03:44:43 +00:00
2015-11-19 17:43:47 +00:00
if ( lp - > state = = FC_PORTDB_STATE_NIL )
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
continue ;
2015-11-19 17:43:47 +00:00
if ( lp - > probational & & lp - > state ! = FC_PORTDB_STATE_ZOMBIE )
lp - > state = FC_PORTDB_STATE_DEAD ;
2006-11-02 03:21:32 +00:00
switch ( lp - > state ) {
case FC_PORTDB_STATE_DEAD :
lp - > state = FC_PORTDB_STATE_NIL ;
2015-07-13 15:11:05 +00:00
isp_async ( isp , ISPASYNC_DEV_GONE , chan , lp ) ;
2016-05-17 13:18:57 +00:00
if ( ( lp - > portid & 0xffff00 ) ! = 0 ) {
2009-09-21 01:38:22 +00:00
( void ) isp_plogx ( isp , chan , lp - > handle ,
lp - > portid ,
PLOGX_FLG_CMD_LOGO |
PLOGX_FLG_IMPLICIT |
2015-12-26 06:13:01 +00:00
PLOGX_FLG_FREE_NPHDL ) ;
2001-02-11 03:44:43 +00:00
}
2006-11-14 08:45:48 +00:00
/*
* Note that we might come out of this with our state
* set to FC_PORTDB_STATE_ZOMBIE .
*/
2006-11-02 03:21:32 +00:00
break ;
case FC_PORTDB_STATE_NEW :
lp - > state = FC_PORTDB_STATE_VALID ;
2009-08-01 01:04:26 +00:00
isp_async ( isp , ISPASYNC_DEV_ARRIVED , chan , lp ) ;
2006-11-02 03:21:32 +00:00
break ;
case FC_PORTDB_STATE_CHANGED :
lp - > state = FC_PORTDB_STATE_VALID ;
2009-08-01 01:04:26 +00:00
isp_async ( isp , ISPASYNC_DEV_CHANGED , chan , lp ) ;
2015-07-13 15:11:05 +00:00
lp - > portid = lp - > new_portid ;
Fix CRN resets in the isp(4) driver in certain situations.
The Command Reference Number (CRN) is part of the FC-Tape features
that we enable when talking to tape drives. It starts at 1, and
goes to 255 and wraps around to 1. There are a number of reset
type conditions that result in the CRN getting reset to 1. These
are detailed in section 4.10 (table 8) of the FCP-4r02b specification.
One of the conditions is when a PRLI (Process Login) is sent by
the initiator, and the Establish Image Pair bit is set in Word 0
of the PRLI.
Previously, the isp(4) driver core sent a notification via
isp_async() that the target had changed or stayed in place, but
there was no indication of whether a PRLI was sent and whether the
Establish Image Pair bit was set.
The result of this was that in some situations, notably
switching back and forth between a direct connection and a switch
connection to a tape drive, the isp(4) driver would fail to reset
the CRN in situations that require it according to the spec. When
the CRN isn't reset in a situation that requires it, the tape drive
then rejects every subsequent command that is sent to the drive.
It is assuming that the commands are being sent out of order.
So, modify the isp(4) driver to include Word 0 of the PRLI command
when it sends isp_async() notifications of target changes. Look at
the Establish Image Pair bit, and reset the CRN if that bit is set.
With this change, I am able to switch a tape drive back and forth
between a direct connection and a switch connection, and the isp(4)
driver resets the CRN when it should.
sys/dev/isp_stds.h:
Add bit definitions for PRLI Word 0.
sys/dev/ispmbox.h:
Add PRLI Word 0 to the port database type, isp_pdb_t.
sys/dev/ispvar.h
Add PRLI Word 0 to fcportdb_t.
sys/dev/isp.c:
Populate the new prli_word0 parameter in the port database.
In isp_pdb_add_update(), add a check to see if the
Establish Image Pair bit is set in PRLI Word 0. If it is,
then that is an additional reason to create a change
notification.
sys/dev/isp_freebsd.c:
In isp_async(), if the device changed or stayed, look at
PRLI Word 0 to see if the Establish Image Pair bit is set.
If it is, reset the CRN if we haven't already.
MFC after: 1 week
Sponsored by: Spectra Logic
Differential Revision: https://reviews.freebsd.org/D19472
2019-03-11 14:21:14 +00:00
lp - > prli_word0 = lp - > new_prli_word0 ;
2015-07-13 15:11:05 +00:00
lp - > prli_word3 = lp - > new_prli_word3 ;
2006-11-02 03:21:32 +00:00
break ;
2015-11-19 17:43:47 +00:00
case FC_PORTDB_STATE_VALID :
2009-08-01 01:04:26 +00:00
isp_async ( isp , ISPASYNC_DEV_STAYED , chan , lp ) ;
2006-11-14 08:45:48 +00:00
break ;
case FC_PORTDB_STATE_ZOMBIE :
2006-11-02 03:21:32 +00:00
break ;
default :
2006-11-14 08:45:48 +00:00
isp_prt ( isp , ISP_LOGWARN ,
2015-07-13 15:11:05 +00:00
" isp_pdb_sync: state %d for idx %d " ,
2006-11-02 03:21:32 +00:00
lp - > state , dbidx ) ;
2009-08-01 01:04:26 +00:00
isp_dump_portdb ( isp , chan ) ;
2001-02-11 03:44:43 +00:00
}
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
}
2006-11-02 03:21:32 +00:00
2015-11-26 13:04:58 +00:00
if ( fcp - > isp_loopstate < LOOP_SYNCING_PDB ) {
isp_prt ( isp , ISP_LOG_SANCFG ,
" Chan %d FC PDB sync aborted " , chan ) ;
return ( 1 ) ;
}
2001-02-11 03:44:43 +00:00
fcp - > isp_loopstate = LOOP_READY ;
2015-11-17 16:33:46 +00:00
isp_prt ( isp , ISP_LOG_SANCFG , " Chan %d FC PDB sync done " , chan ) ;
2001-02-11 03:44:43 +00:00
return ( 0 ) ;
}
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
2015-11-19 17:43:47 +00:00
static void
isp_pdb_add_update ( ispsoftc_t * isp , int chan , isp_pdb_t * pdb )
{
fcportdb_t * lp ;
uint64_t wwnn , wwpn ;
MAKE_WWN_FROM_NODE_NAME ( wwnn , pdb - > nodename ) ;
MAKE_WWN_FROM_NODE_NAME ( wwpn , pdb - > portname ) ;
/* Search port database for the same WWPN. */
if ( isp_find_pdb_by_wwpn ( isp , chan , wwpn , & lp ) ) {
if ( ! lp - > probational ) {
isp_prt ( isp , ISP_LOGERR ,
" Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x) " ,
chan , lp - > portid , lp - > handle ,
FC_PORTDB_TGT ( isp , chan , lp ) , lp - > state ) ;
isp_dump_portdb ( isp , chan ) ;
return ;
}
lp - > probational = 0 ;
lp - > node_wwn = wwnn ;
/* Old device, nothing new. */
if ( lp - > portid = = pdb - > portid & &
lp - > handle = = pdb - > handle & &
Fix CRN resets in the isp(4) driver in certain situations.
The Command Reference Number (CRN) is part of the FC-Tape features
that we enable when talking to tape drives. It starts at 1, and
goes to 255 and wraps around to 1. There are a number of reset
type conditions that result in the CRN getting reset to 1. These
are detailed in section 4.10 (table 8) of the FCP-4r02b specification.
One of the conditions is when a PRLI (Process Login) is sent by
the initiator, and the Establish Image Pair bit is set in Word 0
of the PRLI.
Previously, the isp(4) driver core sent a notification via
isp_async() that the target had changed or stayed in place, but
there was no indication of whether a PRLI was sent and whether the
Establish Image Pair bit was set.
The result of this was that in some situations, notably
switching back and forth between a direct connection and a switch
connection to a tape drive, the isp(4) driver would fail to reset
the CRN in situations that require it according to the spec. When
the CRN isn't reset in a situation that requires it, the tape drive
then rejects every subsequent command that is sent to the drive.
It is assuming that the commands are being sent out of order.
So, modify the isp(4) driver to include Word 0 of the PRLI command
when it sends isp_async() notifications of target changes. Look at
the Establish Image Pair bit, and reset the CRN if that bit is set.
With this change, I am able to switch a tape drive back and forth
between a direct connection and a switch connection, and the isp(4)
driver resets the CRN when it should.
sys/dev/isp_stds.h:
Add bit definitions for PRLI Word 0.
sys/dev/ispmbox.h:
Add PRLI Word 0 to the port database type, isp_pdb_t.
sys/dev/ispvar.h
Add PRLI Word 0 to fcportdb_t.
sys/dev/isp.c:
Populate the new prli_word0 parameter in the port database.
In isp_pdb_add_update(), add a check to see if the
Establish Image Pair bit is set in PRLI Word 0. If it is,
then that is an additional reason to create a change
notification.
sys/dev/isp_freebsd.c:
In isp_async(), if the device changed or stayed, look at
PRLI Word 0 to see if the Establish Image Pair bit is set.
If it is, reset the CRN if we haven't already.
MFC after: 1 week
Sponsored by: Spectra Logic
Differential Revision: https://reviews.freebsd.org/D19472
2019-03-11 14:21:14 +00:00
lp - > prli_word3 = = pdb - > prli_word3 & &
Fix FC-Tape bugs caused in part by r345008.
The point of r345008 was to reset the Command Reference Number (CRN)
in some situations where a device stayed in the topology, but had
changed somehow.
This can include moving from a switch connection to a direct
connection or vice versa, or a device that temporarily goes away
and comes back. (e.g. moving to a different switch port)
There were a couple of bugs in that change:
- We were reporting that a device had not changed whenever the
Establish Image Pair bit was not set. That is not quite correct.
Instead, if the Establish Image Pair bit stays the same (set or
not), the device hasn't changed in that way.
- We weren't setting PRLI Word0 in the port database when a new
device arrived, so comparisons with the old value for the
Establish Image Pair bit weren't really possible. So, make sure
PRLI Word0 is set in the port database for new devices.
- We were resetting the CRN whenever the Establish Image Pair bit
was set for a device, even when the device had stayed the same
and the value of the bit hadn't changed. Now, only reset the
CRN for devices that have changed, not devices that sayed the
same.
The result of all of this was that if we had a single FC device on
an FC port and it went away and came back, we would wind up
correctly resetting the CRN.
But, if we had multiple devices connected via a switch, and there
was any change in one or more of those devices, all of the devices
that stayed the same would also have their CRN values reset.
The result, from a user standpoint, is that the tape drives, etc.
would all start to time out commands and the initiator would send
aborts.
sys/dev/isp/isp.c:
In isp_pdb_add_update(), look at whether the Establish
Image Pair bit has changed as part of the check to
determine whether a device is still the same. This was
causing erroneous change notifications. Also, when
creating a new port database entry, initialize the
PRLI Word 0 values.
sys/dev/isp/isp_freebsd.c:
In isp_async(), in the changed/stayed case, instead of
looking at the Establish Image Pair bit to determine
whether to reset the CRN, look at the command value.
(Changed vs. Stayed.) Only reset the CRN for devices
that have changed.
Sponsored by: Spectra Logic
MFC after: 3 days
2019-05-24 17:58:29 +00:00
( ( pdb - > prli_word0 & PRLI_WD0_EST_IMAGE_PAIR ) = =
( lp - > prli_word0 & PRLI_WD0_EST_IMAGE_PAIR ) ) ) {
2015-11-19 17:43:47 +00:00
if ( lp - > state ! = FC_PORTDB_STATE_NEW )
lp - > state = FC_PORTDB_STATE_VALID ;
isp_prt ( isp , ISP_LOG_SANCFG ,
" Chan %d Port 0x%06x@0x%04x is valid " ,
chan , pdb - > portid , pdb - > handle ) ;
return ;
}
/* Something has changed. */
lp - > state = FC_PORTDB_STATE_CHANGED ;
lp - > handle = pdb - > handle ;
lp - > new_portid = pdb - > portid ;
Fix CRN resets in the isp(4) driver in certain situations.
The Command Reference Number (CRN) is part of the FC-Tape features
that we enable when talking to tape drives. It starts at 1, and
goes to 255 and wraps around to 1. There are a number of reset
type conditions that result in the CRN getting reset to 1. These
are detailed in section 4.10 (table 8) of the FCP-4r02b specification.
One of the conditions is when a PRLI (Process Login) is sent by
the initiator, and the Establish Image Pair bit is set in Word 0
of the PRLI.
Previously, the isp(4) driver core sent a notification via
isp_async() that the target had changed or stayed in place, but
there was no indication of whether a PRLI was sent and whether the
Establish Image Pair bit was set.
The result of this was that in some situations, notably
switching back and forth between a direct connection and a switch
connection to a tape drive, the isp(4) driver would fail to reset
the CRN in situations that require it according to the spec. When
the CRN isn't reset in a situation that requires it, the tape drive
then rejects every subsequent command that is sent to the drive.
It is assuming that the commands are being sent out of order.
So, modify the isp(4) driver to include Word 0 of the PRLI command
when it sends isp_async() notifications of target changes. Look at
the Establish Image Pair bit, and reset the CRN if that bit is set.
With this change, I am able to switch a tape drive back and forth
between a direct connection and a switch connection, and the isp(4)
driver resets the CRN when it should.
sys/dev/isp_stds.h:
Add bit definitions for PRLI Word 0.
sys/dev/ispmbox.h:
Add PRLI Word 0 to the port database type, isp_pdb_t.
sys/dev/ispvar.h
Add PRLI Word 0 to fcportdb_t.
sys/dev/isp.c:
Populate the new prli_word0 parameter in the port database.
In isp_pdb_add_update(), add a check to see if the
Establish Image Pair bit is set in PRLI Word 0. If it is,
then that is an additional reason to create a change
notification.
sys/dev/isp_freebsd.c:
In isp_async(), if the device changed or stayed, look at
PRLI Word 0 to see if the Establish Image Pair bit is set.
If it is, reset the CRN if we haven't already.
MFC after: 1 week
Sponsored by: Spectra Logic
Differential Revision: https://reviews.freebsd.org/D19472
2019-03-11 14:21:14 +00:00
lp - > new_prli_word0 = pdb - > prli_word0 ;
2015-11-19 17:43:47 +00:00
lp - > new_prli_word3 = pdb - > prli_word3 ;
isp_prt ( isp , ISP_LOG_SANCFG ,
" Chan %d Port 0x%06x@0x%04x is changed " ,
chan , pdb - > portid , pdb - > handle ) ;
return ;
}
/* It seems like a new port. Find an empty slot for it. */
if ( ! isp_find_pdb_empty ( isp , chan , & lp ) ) {
isp_prt ( isp , ISP_LOGERR , " Chan %d out of portdb entries " , chan ) ;
return ;
}
ISP_MEMZERO ( lp , sizeof ( fcportdb_t ) ) ;
lp - > probational = 0 ;
lp - > state = FC_PORTDB_STATE_NEW ;
lp - > portid = lp - > new_portid = pdb - > portid ;
Fix FC-Tape bugs caused in part by r345008.
The point of r345008 was to reset the Command Reference Number (CRN)
in some situations where a device stayed in the topology, but had
changed somehow.
This can include moving from a switch connection to a direct
connection or vice versa, or a device that temporarily goes away
and comes back. (e.g. moving to a different switch port)
There were a couple of bugs in that change:
- We were reporting that a device had not changed whenever the
Establish Image Pair bit was not set. That is not quite correct.
Instead, if the Establish Image Pair bit stays the same (set or
not), the device hasn't changed in that way.
- We weren't setting PRLI Word0 in the port database when a new
device arrived, so comparisons with the old value for the
Establish Image Pair bit weren't really possible. So, make sure
PRLI Word0 is set in the port database for new devices.
- We were resetting the CRN whenever the Establish Image Pair bit
was set for a device, even when the device had stayed the same
and the value of the bit hadn't changed. Now, only reset the
CRN for devices that have changed, not devices that sayed the
same.
The result of all of this was that if we had a single FC device on
an FC port and it went away and came back, we would wind up
correctly resetting the CRN.
But, if we had multiple devices connected via a switch, and there
was any change in one or more of those devices, all of the devices
that stayed the same would also have their CRN values reset.
The result, from a user standpoint, is that the tape drives, etc.
would all start to time out commands and the initiator would send
aborts.
sys/dev/isp/isp.c:
In isp_pdb_add_update(), look at whether the Establish
Image Pair bit has changed as part of the check to
determine whether a device is still the same. This was
causing erroneous change notifications. Also, when
creating a new port database entry, initialize the
PRLI Word 0 values.
sys/dev/isp/isp_freebsd.c:
In isp_async(), in the changed/stayed case, instead of
looking at the Establish Image Pair bit to determine
whether to reset the CRN, look at the command value.
(Changed vs. Stayed.) Only reset the CRN for devices
that have changed.
Sponsored by: Spectra Logic
MFC after: 3 days
2019-05-24 17:58:29 +00:00
lp - > prli_word0 = lp - > new_prli_word0 = pdb - > prli_word0 ;
2015-11-19 17:43:47 +00:00
lp - > prli_word3 = lp - > new_prli_word3 = pdb - > prli_word3 ;
lp - > handle = pdb - > handle ;
lp - > port_wwn = wwpn ;
lp - > node_wwn = wwnn ;
isp_prt ( isp , ISP_LOG_SANCFG , " Chan %d Port 0x%06x@0x%04x is new " ,
chan , pdb - > portid , pdb - > handle ) ;
}
2006-11-02 03:21:32 +00:00
/*
* Scan local loop for devices .
*/
2001-02-11 03:44:43 +00:00
static int
2009-08-01 01:04:26 +00:00
isp_scan_loop ( ispsoftc_t * isp , int chan )
2001-02-11 03:44:43 +00:00
{
2009-08-01 01:04:26 +00:00
fcparam * fcp = FCPARAM ( isp , chan ) ;
2015-11-19 17:43:47 +00:00
int idx , lim , r ;
2001-02-11 03:44:43 +00:00
isp_pdb_t pdb ;
2015-12-27 06:28:31 +00:00
uint16_t * handles ;
2015-10-28 12:34:59 +00:00
uint16_t handle ;
2006-11-02 03:21:32 +00:00
2015-11-26 13:04:58 +00:00
if ( fcp - > isp_loopstate < LOOP_LTEST_DONE )
2006-11-02 03:21:32 +00:00
return ( - 1 ) ;
2015-11-26 13:04:58 +00:00
if ( fcp - > isp_loopstate > = LOOP_LSCAN_DONE )
2006-11-02 03:21:32 +00:00
return ( 0 ) ;
2015-11-26 13:04:58 +00:00
2015-11-17 16:33:46 +00:00
isp_prt ( isp , ISP_LOG_SANCFG , " Chan %d FC loop scan " , chan ) ;
2015-11-21 21:01:00 +00:00
fcp - > isp_loopstate = LOOP_SCANNING_LOOP ;
2015-11-19 17:43:47 +00:00
if ( TOPO_IS_FABRIC ( fcp - > isp_topo ) ) {
2015-10-28 12:34:59 +00:00
isp_prt ( isp , ISP_LOG_SANCFG ,
2015-11-17 16:33:46 +00:00
" Chan %d FC loop scan done (no loop) " , chan ) ;
2001-02-11 03:44:43 +00:00
fcp - > isp_loopstate = LOOP_LSCAN_DONE ;
return ( 0 ) ;
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
}
2006-11-14 08:45:48 +00:00
2015-12-27 06:28:31 +00:00
handles = ( uint16_t * ) fcp - > isp_scanscratch ;
lim = ISP_FC_SCRLEN / 2 ;
r = isp_gethandles ( isp , chan , handles , & lim , 1 ) ;
2015-10-28 12:34:59 +00:00
if ( r ! = 0 ) {
isp_prt ( isp , ISP_LOG_SANCFG ,
2015-11-17 16:33:46 +00:00
" Chan %d Getting list of handles failed with %x " , chan , r ) ;
2015-10-28 12:34:59 +00:00
isp_prt ( isp , ISP_LOG_SANCFG ,
2015-11-17 16:33:46 +00:00
" Chan %d FC loop scan done (bad) " , chan ) ;
2015-10-28 12:34:59 +00:00
return ( - 1 ) ;
}
2015-11-17 16:33:46 +00:00
isp_prt ( isp , ISP_LOG_SANCFG , " Chan %d Got %d handles " ,
2015-10-28 12:34:59 +00:00
chan , lim ) ;
2006-07-03 08:24:09 +00:00
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
/*
2006-11-02 03:21:32 +00:00
* Run through the list and get the port database info for each one .
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
*/
2015-11-21 21:01:00 +00:00
isp_mark_portdb ( isp , chan ) ;
2015-10-28 12:34:59 +00:00
for ( idx = 0 ; idx < lim ; idx + + ) {
handle = handles [ idx ] ;
2001-02-11 03:44:43 +00:00
/*
2009-08-01 01:04:26 +00:00
* Don ' t scan " special " ids .
*/
2020-11-20 01:15:48 +00:00
if ( handle > = NPH_RESERVED )
continue ;
2001-01-09 02:46:23 +00:00
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
/*
2006-11-02 03:21:32 +00:00
* Get the port database entity for this index .
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
*/
2015-12-27 06:28:31 +00:00
r = isp_getpdb ( isp , chan , handle , & pdb ) ;
2020-11-20 01:15:48 +00:00
if ( fcp - > isp_loopstate < LOOP_SCANNING_LOOP ) {
abort :
isp_prt ( isp , ISP_LOG_SANCFG ,
" Chan %d FC loop scan aborted " , chan ) ;
return ( 1 ) ;
}
2009-08-01 01:04:26 +00:00
if ( r ! = 0 ) {
isp_prt ( isp , ISP_LOGDEBUG1 ,
2015-11-17 16:33:46 +00:00
" Chan %d FC Scan Loop handle %d returned %x " ,
2009-08-01 01:04:26 +00:00
chan , handle , r ) ;
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
continue ;
2006-11-02 03:21:32 +00:00
}
2015-11-19 17:43:47 +00:00
isp_pdb_add_update ( isp , chan , & pdb ) ;
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
}
2015-11-17 16:33:46 +00:00
if ( fcp - > isp_loopstate < LOOP_SCANNING_LOOP )
goto abort ;
2006-11-02 03:21:32 +00:00
fcp - > isp_loopstate = LOOP_LSCAN_DONE ;
2015-11-17 16:33:46 +00:00
isp_prt ( isp , ISP_LOG_SANCFG , " Chan %d FC loop scan done " , chan ) ;
2002-04-04 23:46:01 +00:00
return ( 0 ) ;
}
2006-11-02 03:21:32 +00:00
static int
2016-04-09 11:54:09 +00:00
isp_ct_passthru ( ispsoftc_t * isp , int chan , uint32_t cmd_bcnt , uint32_t rsp_bcnt )
2006-11-02 03:21:32 +00:00
{
2009-08-01 01:04:26 +00:00
fcparam * fcp = FCPARAM ( isp , chan ) ;
2016-04-12 18:50:37 +00:00
isp_ct_pt_t pt ;
2020-11-27 15:50:20 +00:00
int retval ;
2006-11-02 03:21:32 +00:00
2017-07-02 14:59:41 +00:00
if ( isp - > isp_dblev & ISP_LOGDEBUG1 )
isp_print_bytes ( isp , " CT request " , cmd_bcnt , fcp - > isp_scratch ) ;
2006-11-02 03:21:32 +00:00
/*
* Build a Passthrough IOCB in memory .
*/
2016-04-12 18:50:37 +00:00
ISP_MEMZERO ( & pt , sizeof ( pt ) ) ;
pt . ctp_header . rqs_entry_count = 1 ;
pt . ctp_header . rqs_entry_type = RQSTYPE_CT_PASSTHRU ;
pt . ctp_nphdl = fcp - > isp_sns_hdl ;
pt . ctp_cmd_cnt = 1 ;
pt . ctp_vpidx = ISP_GET_VPIDX ( isp , chan ) ;
pt . ctp_time = 10 ;
pt . ctp_rsp_cnt = 1 ;
pt . ctp_rsp_bcnt = rsp_bcnt ;
pt . ctp_cmd_bcnt = cmd_bcnt ;
2016-04-16 06:36:56 +00:00
pt . ctp_dataseg [ 0 ] . ds_base = DMA_LO32 ( fcp - > isp_scdma ) ;
pt . ctp_dataseg [ 0 ] . ds_basehi = DMA_HI32 ( fcp - > isp_scdma ) ;
2016-04-12 18:50:37 +00:00
pt . ctp_dataseg [ 0 ] . ds_count = cmd_bcnt ;
pt . ctp_dataseg [ 1 ] . ds_base = DMA_LO32 ( fcp - > isp_scdma ) ;
pt . ctp_dataseg [ 1 ] . ds_basehi = DMA_HI32 ( fcp - > isp_scdma ) ;
pt . ctp_dataseg [ 1 ] . ds_count = rsp_bcnt ;
2006-11-02 03:21:32 +00:00
2020-11-27 15:50:20 +00:00
retval = isp_exec_entry_queue ( isp , & pt , & pt , 2 * pt . ctp_time ) ;
if ( retval ! = 0 ) {
isp_prt ( isp , ISP_LOGERR , " %s: CTP of chan %d error %d " ,
__func__ , chan , retval ) ;
return ( retval ) ;
2016-04-12 18:50:37 +00:00
}
if ( pt . ctp_status & & pt . ctp_status ! = RQCS_DATA_UNDERRUN ) {
2009-08-01 01:04:26 +00:00
isp_prt ( isp , ISP_LOGWARN ,
2017-07-03 15:56:45 +00:00
" Chan %d CT pass-through returned 0x%x " ,
2016-04-12 18:50:37 +00:00
chan , pt . ctp_status ) ;
2006-11-02 03:21:32 +00:00
return ( - 1 ) ;
}
2016-04-09 11:54:09 +00:00
2017-07-02 14:59:41 +00:00
if ( isp - > isp_dblev & ISP_LOGDEBUG1 )
isp_print_bytes ( isp , " CT response " , rsp_bcnt , fcp - > isp_scratch ) ;
2016-04-09 11:54:09 +00:00
return ( 0 ) ;
}
2017-07-02 15:08:32 +00:00
/*
* Scan the fabric for devices and add them to our port database .
*
2017-07-03 15:56:45 +00:00
* Use the GID_PT command to get list of all Nx_Port IDs SNS knows .
* Use GFF_ID and GFT_ID to check port type ( FCP ) and features ( target ) .
2017-07-02 15:08:32 +00:00
*
2020-11-20 01:15:48 +00:00
* We use CT Pass - through IOCB .
2017-07-02 15:08:32 +00:00
*/
# define GIDLEN ISP_FC_SCRLEN
# define NGENT ((GIDLEN - 16) >> 2)
2016-04-09 11:54:09 +00:00
static int
2017-07-03 15:56:45 +00:00
isp_gid_pt ( ispsoftc_t * isp , int chan )
2016-04-09 11:54:09 +00:00
{
fcparam * fcp = FCPARAM ( isp , chan ) ;
ct_hdr_t ct ;
uint8_t * scp = fcp - > isp_scratch ;
2017-07-03 15:56:45 +00:00
isp_prt ( isp , ISP_LOGDEBUG0 , " Chan %d requesting GID_PT " , chan ) ;
2016-04-09 11:54:09 +00:00
if ( FC_SCRATCH_ACQUIRE ( isp , chan ) ) {
isp_prt ( isp , ISP_LOGERR , sacq ) ;
return ( - 1 ) ;
}
2020-11-20 01:15:48 +00:00
/* Build the CT command and execute via pass-through. */
ISP_MEMZERO ( & ct , sizeof ( ct ) ) ;
ct . ct_revision = CT_REVISION ;
ct . ct_fcs_type = CT_FC_TYPE_FC ;
ct . ct_fcs_subtype = CT_FC_SUBTYPE_NS ;
ct . ct_cmd_resp = SNS_GID_PT ;
ct . ct_bcnt_resid = ( GIDLEN - 16 ) > > 2 ;
isp_put_ct_hdr ( isp , & ct , ( ct_hdr_t * ) scp ) ;
scp [ sizeof ( ct ) ] = 0x7f ; /* Port Type = Nx_Port */
scp [ sizeof ( ct ) + 1 ] = 0 ; /* Domain_ID = any */
scp [ sizeof ( ct ) + 2 ] = 0 ; /* Area_ID = any */
scp [ sizeof ( ct ) + 3 ] = 0 ; /* Flags = no Area_ID */
if ( isp_ct_passthru ( isp , chan , sizeof ( ct ) + sizeof ( uint32_t ) , GIDLEN ) ) {
FC_SCRATCH_RELEASE ( isp , chan ) ;
return ( - 1 ) ;
2016-04-09 11:54:09 +00:00
}
2017-07-03 15:56:45 +00:00
isp_get_gid_xx_response ( isp , ( sns_gid_xx_rsp_t * ) scp ,
( sns_gid_xx_rsp_t * ) fcp - > isp_scanscratch , NGENT ) ;
2015-12-27 06:28:31 +00:00
FC_SCRATCH_RELEASE ( isp , chan ) ;
2006-11-02 03:21:32 +00:00
return ( 0 ) ;
}
2017-07-03 15:56:45 +00:00
static int
isp_gff_id ( ispsoftc_t * isp , int chan , uint32_t portid )
{
fcparam * fcp = FCPARAM ( isp , chan ) ;
ct_hdr_t ct ;
uint32_t * rp ;
uint8_t * scp = fcp - > isp_scratch ;
sns_gff_id_rsp_t rsp ;
int i , res = - 1 ;
if ( ! fcp - > isp_use_gff_id ) /* User may block GFF_ID use. */
return ( res ) ;
isp_prt ( isp , ISP_LOGDEBUG0 , " Chan %d requesting GFF_ID " , chan ) ;
if ( FC_SCRATCH_ACQUIRE ( isp , chan ) ) {
isp_prt ( isp , ISP_LOGERR , sacq ) ;
return ( res ) ;
}
/* Build the CT command and execute via pass-through. */
ISP_MEMZERO ( & ct , sizeof ( ct ) ) ;
ct . ct_revision = CT_REVISION ;
ct . ct_fcs_type = CT_FC_TYPE_FC ;
ct . ct_fcs_subtype = CT_FC_SUBTYPE_NS ;
ct . ct_cmd_resp = SNS_GFF_ID ;
ct . ct_bcnt_resid = ( SNS_GFF_ID_RESP_SIZE - sizeof ( ct ) ) / 4 ;
isp_put_ct_hdr ( isp , & ct , ( ct_hdr_t * ) scp ) ;
rp = ( uint32_t * ) & scp [ sizeof ( ct ) ] ;
ISP_IOZPUT_32 ( isp , portid , rp ) ;
if ( isp_ct_passthru ( isp , chan , sizeof ( ct ) + sizeof ( uint32_t ) ,
SNS_GFF_ID_RESP_SIZE ) ) {
FC_SCRATCH_RELEASE ( isp , chan ) ;
return ( res ) ;
}
isp_get_gff_id_response ( isp , ( sns_gff_id_rsp_t * ) scp , & rsp ) ;
if ( rsp . snscb_cthdr . ct_cmd_resp = = LS_ACC ) {
for ( i = 0 ; i < 32 ; i + + ) {
if ( rsp . snscb_fc4_features [ i ] ! = 0 ) {
res = 0 ;
break ;
}
}
if ( ( ( rsp . snscb_fc4_features [ FC4_SCSI / 8 ] > >
( ( FC4_SCSI % 8 ) * 4 ) ) & 0x01 ) ! = 0 )
res = 1 ;
/* Workaround for broken Brocade firmware. */
if ( ( ( ISP_SWAP32 ( isp , rsp . snscb_fc4_features [ FC4_SCSI / 8 ] ) > >
( ( FC4_SCSI % 8 ) * 4 ) ) & 0x01 ) ! = 0 )
res = 1 ;
}
FC_SCRATCH_RELEASE ( isp , chan ) ;
isp_prt ( isp , ISP_LOGDEBUG0 , " Chan %d GFF_ID result is %d " , chan , res ) ;
return ( res ) ;
}
static int
isp_gft_id ( ispsoftc_t * isp , int chan , uint32_t portid )
{
fcparam * fcp = FCPARAM ( isp , chan ) ;
ct_hdr_t ct ;
uint32_t * rp ;
uint8_t * scp = fcp - > isp_scratch ;
sns_gft_id_rsp_t rsp ;
int i , res = - 1 ;
if ( ! fcp - > isp_use_gft_id ) /* User may block GFT_ID use. */
return ( res ) ;
isp_prt ( isp , ISP_LOGDEBUG0 , " Chan %d requesting GFT_ID " , chan ) ;
if ( FC_SCRATCH_ACQUIRE ( isp , chan ) ) {
isp_prt ( isp , ISP_LOGERR , sacq ) ;
return ( res ) ;
}
2020-11-20 01:15:48 +00:00
/* Build the CT command and execute via pass-through. */
ISP_MEMZERO ( & ct , sizeof ( ct ) ) ;
ct . ct_revision = CT_REVISION ;
ct . ct_fcs_type = CT_FC_TYPE_FC ;
ct . ct_fcs_subtype = CT_FC_SUBTYPE_NS ;
ct . ct_cmd_resp = SNS_GFT_ID ;
ct . ct_bcnt_resid = ( SNS_GFT_ID_RESP_SIZE - sizeof ( ct ) ) / 4 ;
isp_put_ct_hdr ( isp , & ct , ( ct_hdr_t * ) scp ) ;
rp = ( uint32_t * ) & scp [ sizeof ( ct ) ] ;
ISP_IOZPUT_32 ( isp , portid , rp ) ;
if ( isp_ct_passthru ( isp , chan , sizeof ( ct ) + sizeof ( uint32_t ) ,
SNS_GFT_ID_RESP_SIZE ) ) {
FC_SCRATCH_RELEASE ( isp , chan ) ;
return ( res ) ;
2017-07-03 15:56:45 +00:00
}
isp_get_gft_id_response ( isp , ( sns_gft_id_rsp_t * ) scp , & rsp ) ;
if ( rsp . snscb_cthdr . ct_cmd_resp = = LS_ACC ) {
for ( i = 0 ; i < 8 ; i + + ) {
if ( rsp . snscb_fc4_types [ i ] ! = 0 ) {
res = 0 ;
break ;
}
}
if ( ( ( rsp . snscb_fc4_types [ FC4_SCSI / 32 ] > >
( FC4_SCSI % 32 ) ) & 0x01 ) ! = 0 )
res = 1 ;
}
FC_SCRATCH_RELEASE ( isp , chan ) ;
isp_prt ( isp , ISP_LOGDEBUG0 , " Chan %d GFT_ID result is %d " , chan , res ) ;
return ( res ) ;
}
2006-11-02 03:21:32 +00:00
static int
2009-08-01 01:04:26 +00:00
isp_scan_fabric ( ispsoftc_t * isp , int chan )
2006-11-02 03:21:32 +00:00
{
2009-08-01 01:04:26 +00:00
fcparam * fcp = FCPARAM ( isp , chan ) ;
2015-11-19 17:43:47 +00:00
fcportdb_t * lp ;
2006-11-02 03:21:32 +00:00
uint32_t portid ;
2009-08-01 01:04:26 +00:00
isp_pdb_t pdb ;
2006-11-02 03:21:32 +00:00
int portidx , portlim , r ;
2017-07-03 15:56:45 +00:00
sns_gid_xx_rsp_t * rs ;
2006-11-02 03:21:32 +00:00
2015-11-26 13:04:58 +00:00
if ( fcp - > isp_loopstate < LOOP_LSCAN_DONE )
2002-04-04 23:46:01 +00:00
return ( - 1 ) ;
2015-11-26 13:04:58 +00:00
if ( fcp - > isp_loopstate > = LOOP_FSCAN_DONE )
2006-11-02 03:21:32 +00:00
return ( 0 ) ;
2015-11-26 13:04:58 +00:00
2015-11-17 16:33:46 +00:00
isp_prt ( isp , ISP_LOG_SANCFG , " Chan %d FC fabric scan " , chan ) ;
2015-11-21 21:01:00 +00:00
fcp - > isp_loopstate = LOOP_SCANNING_FABRIC ;
2015-11-19 17:43:47 +00:00
if ( ! TOPO_IS_FABRIC ( fcp - > isp_topo ) ) {
2006-11-02 03:21:32 +00:00
fcp - > isp_loopstate = LOOP_FSCAN_DONE ;
2015-11-17 16:33:46 +00:00
isp_prt ( isp , ISP_LOG_SANCFG ,
" Chan %d FC fabric scan done (no fabric) " , chan ) ;
2006-11-02 03:21:32 +00:00
return ( 0 ) ;
}
2015-11-17 16:33:46 +00:00
2009-08-01 01:04:26 +00:00
if ( fcp - > isp_loopstate < LOOP_SCANNING_FABRIC ) {
2015-11-17 16:33:46 +00:00
abort :
2009-08-01 01:04:26 +00:00
FC_SCRATCH_RELEASE ( isp , chan ) ;
2015-11-17 16:33:46 +00:00
isp_prt ( isp , ISP_LOG_SANCFG ,
2015-11-26 13:04:58 +00:00
" Chan %d FC fabric scan aborted " , chan ) ;
return ( 1 ) ;
2009-08-01 01:04:26 +00:00
}
/*
* Make sure we still are logged into the fabric controller .
*/
2020-11-20 01:15:48 +00:00
r = isp_getpdb ( isp , chan , NPH_FL_ID , & pdb ) ;
2015-10-28 12:34:59 +00:00
if ( ( r & 0xffff ) = = MBOX_NOT_LOGGED_IN ) {
2015-12-27 06:28:31 +00:00
isp_dump_chip_portdb ( isp , chan ) ;
2009-08-01 01:04:26 +00:00
}
if ( r ) {
2015-11-17 16:33:46 +00:00
fcp - > isp_loopstate = LOOP_LTEST_DONE ;
2015-12-27 06:28:31 +00:00
fail :
isp_prt ( isp , ISP_LOG_SANCFG ,
" Chan %d FC fabric scan done (bad) " , chan ) ;
return ( - 1 ) ;
2009-08-01 01:04:26 +00:00
}
2006-11-02 03:21:32 +00:00
2015-11-19 17:43:47 +00:00
/* Get list of port IDs from SNS. */
2017-07-03 15:56:45 +00:00
r = isp_gid_pt ( isp , chan ) ;
2015-11-19 17:43:47 +00:00
if ( fcp - > isp_loopstate < LOOP_SCANNING_FABRIC )
2015-11-17 16:33:46 +00:00
goto abort ;
2006-11-02 03:21:32 +00:00
if ( r > 0 ) {
fcp - > isp_loopstate = LOOP_FSCAN_DONE ;
2015-11-26 13:04:58 +00:00
return ( - 1 ) ;
2006-11-02 03:21:32 +00:00
} else if ( r < 0 ) {
2015-11-17 16:33:46 +00:00
fcp - > isp_loopstate = LOOP_LTEST_DONE ; /* try again */
2015-11-26 13:04:58 +00:00
return ( - 1 ) ;
2006-11-02 03:21:32 +00:00
}
2017-07-03 15:56:45 +00:00
rs = ( sns_gid_xx_rsp_t * ) fcp - > isp_scanscratch ;
2015-11-19 17:43:47 +00:00
if ( fcp - > isp_loopstate < LOOP_SCANNING_FABRIC )
2015-11-17 16:33:46 +00:00
goto abort ;
2015-12-27 06:28:31 +00:00
if ( rs - > snscb_cthdr . ct_cmd_resp ! = LS_ACC ) {
2002-06-16 05:18:22 +00:00
int level ;
2017-07-10 06:25:30 +00:00
/* FC-4 Type and Port Type not registered are not errors. */
if ( rs - > snscb_cthdr . ct_reason = = 9 & &
( rs - > snscb_cthdr . ct_explanation = = 0x07 | |
rs - > snscb_cthdr . ct_explanation = = 0x0a ) ) {
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
level = ISP_LOG_SANCFG ;
2006-11-02 03:21:32 +00:00
} else {
2002-06-16 05:18:22 +00:00
level = ISP_LOGWARN ;
2006-11-02 03:21:32 +00:00
}
2017-07-03 15:56:45 +00:00
isp_prt ( isp , level , " Chan %d Fabric Nameserver rejected GID_PT "
2009-08-01 01:04:26 +00:00
" (Reason=0x%x Expl=0x%x) " , chan ,
2015-12-27 06:28:31 +00:00
rs - > snscb_cthdr . ct_reason ,
rs - > snscb_cthdr . ct_explanation ) ;
2002-04-04 23:46:01 +00:00
fcp - > isp_loopstate = LOOP_FSCAN_DONE ;
2015-11-26 13:04:58 +00:00
return ( - 1 ) ;
2002-04-04 23:46:01 +00:00
}
2015-11-19 17:43:47 +00:00
/* Check our buffer was big enough to get the full list. */
2006-11-02 03:21:32 +00:00
for ( portidx = 0 ; portidx < NGENT - 1 ; portidx + + ) {
2015-12-27 06:28:31 +00:00
if ( rs - > snscb_ports [ portidx ] . control & 0x80 )
2006-11-02 03:21:32 +00:00
break ;
}
2015-12-27 06:28:31 +00:00
if ( ( rs - > snscb_ports [ portidx ] . control & 0x80 ) = = 0 ) {
2006-11-02 03:21:32 +00:00
isp_prt ( isp , ISP_LOGWARN ,
2009-08-01 01:04:26 +00:00
" fabric too big for scratch area: increase ISP_FC_SCRLEN " ) ;
2006-11-02 03:21:32 +00:00
}
portlim = portidx + 1 ;
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
isp_prt ( isp , ISP_LOG_SANCFG ,
2015-11-17 16:33:46 +00:00
" Chan %d Got %d ports back from name server " , chan , portlim ) ;
2006-11-02 03:21:32 +00:00
2015-11-19 17:43:47 +00:00
/* Go through the list and remove duplicate port ids. */
2006-11-02 03:21:32 +00:00
for ( portidx = 0 ; portidx < portlim ; portidx + + ) {
int npidx ;
portid =
2015-12-27 06:28:31 +00:00
( ( rs - > snscb_ports [ portidx ] . portid [ 0 ] ) < < 16 ) |
( ( rs - > snscb_ports [ portidx ] . portid [ 1 ] ) < < 8 ) |
( ( rs - > snscb_ports [ portidx ] . portid [ 2 ] ) ) ;
2006-11-02 03:21:32 +00:00
for ( npidx = portidx + 1 ; npidx < portlim ; npidx + + ) {
uint32_t new_portid =
2015-12-27 06:28:31 +00:00
( ( rs - > snscb_ports [ npidx ] . portid [ 0 ] ) < < 16 ) |
( ( rs - > snscb_ports [ npidx ] . portid [ 1 ] ) < < 8 ) |
( ( rs - > snscb_ports [ npidx ] . portid [ 2 ] ) ) ;
2006-11-02 03:21:32 +00:00
if ( new_portid = = portid ) {
break ;
}
}
if ( npidx < portlim ) {
2015-12-27 06:28:31 +00:00
rs - > snscb_ports [ npidx ] . portid [ 0 ] = 0 ;
rs - > snscb_ports [ npidx ] . portid [ 1 ] = 0 ;
rs - > snscb_ports [ npidx ] . portid [ 2 ] = 0 ;
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
isp_prt ( isp , ISP_LOG_SANCFG , " Chan %d removing duplicate PortID 0x%06x entry from list " , chan , portid ) ;
2006-11-02 03:21:32 +00:00
}
}
2002-04-04 23:46:01 +00:00
/*
2009-08-01 01:04:26 +00:00
* We now have a list of Port IDs for all FC4 SCSI devices
2006-11-02 03:21:32 +00:00
* that the Fabric Name server knows about .
2002-04-04 23:46:01 +00:00
*
2006-11-02 03:21:32 +00:00
* For each entry on this list go through our port database looking
* for probational entries - if we find one , then an old entry is
2009-08-01 01:04:26 +00:00
* maybe still this one . We get some information to find out .
2006-11-02 03:21:32 +00:00
*
* Otherwise , it ' s a new fabric device , and we log into it
* ( unconditionally ) . After searching the entire database
* again to make sure that we never ever ever ever have more
* than one entry that has the same PortID or the same
* WWNN / WWPN duple , we enter the device into our database .
2002-04-04 23:46:01 +00:00
*/
2015-11-21 21:01:00 +00:00
isp_mark_portdb ( isp , chan ) ;
2006-11-02 03:21:32 +00:00
for ( portidx = 0 ; portidx < portlim ; portidx + + ) {
2015-12-27 06:28:31 +00:00
portid = ( ( rs - > snscb_ports [ portidx ] . portid [ 0 ] ) < < 16 ) |
( ( rs - > snscb_ports [ portidx ] . portid [ 1 ] ) < < 8 ) |
( ( rs - > snscb_ports [ portidx ] . portid [ 2 ] ) ) ;
2015-11-19 17:43:47 +00:00
isp_prt ( isp , ISP_LOG_SANCFG ,
" Chan %d Checking fabric port 0x%06x " , chan , portid ) ;
2006-11-02 03:21:32 +00:00
if ( portid = = 0 ) {
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
isp_prt ( isp , ISP_LOG_SANCFG ,
2015-11-21 21:01:00 +00:00
" Chan %d Port at idx %d is zero " ,
2009-08-01 01:04:26 +00:00
chan , portidx ) ;
2006-11-02 03:21:32 +00:00
continue ;
}
2015-11-17 16:33:46 +00:00
if ( portid = = fcp - > isp_portid ) {
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
isp_prt ( isp , ISP_LOG_SANCFG ,
2015-11-21 21:01:00 +00:00
" Chan %d Port 0x%06x is our " , chan , portid ) ;
2006-11-02 03:21:32 +00:00
continue ;
2002-04-04 23:46:01 +00:00
}
2009-08-01 01:04:26 +00:00
2015-11-19 17:43:47 +00:00
/* Now search the entire port database for the same portid. */
if ( isp_find_pdb_by_portid ( isp , chan , portid , & lp ) ) {
if ( ! lp - > probational ) {
isp_prt ( isp , ISP_LOGERR ,
" Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x) " ,
chan , lp - > portid , lp - > handle ,
FC_PORTDB_TGT ( isp , chan , lp ) , lp - > state ) ;
isp_dump_portdb ( isp , chan ) ;
goto fail ;
2006-11-02 03:21:32 +00:00
}
2016-05-16 16:44:34 +00:00
if ( lp - > state = = FC_PORTDB_STATE_ZOMBIE )
goto relogin ;
2006-11-02 03:21:32 +00:00
/*
* See if we ' re still logged into it .
*
* If we aren ' t , mark it as a dead device and
* leave the new portid in the database entry
* for somebody further along to decide what to
* do ( policy choice ) .
*
* If we are , check to see if it ' s the same
* device still ( it should be ) . If for some
* reason it isn ' t , mark it as a changed device
* and leave the new portid and role in the
* database entry for somebody further along to
* decide what to do ( policy choice ) .
*/
2015-12-27 06:28:31 +00:00
r = isp_getpdb ( isp , chan , lp - > handle , & pdb ) ;
2015-11-19 17:43:47 +00:00
if ( fcp - > isp_loopstate < LOOP_SCANNING_FABRIC )
2015-11-17 16:33:46 +00:00
goto abort ;
2006-11-02 03:21:32 +00:00
if ( r ! = 0 ) {
lp - > state = FC_PORTDB_STATE_DEAD ;
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
isp_prt ( isp , ISP_LOG_SANCFG ,
2015-11-19 17:43:47 +00:00
" Chan %d Port 0x%06x handle 0x%x is dead (%d) " ,
chan , portid , lp - > handle , r ) ;
goto relogin ;
2006-11-02 03:21:32 +00:00
}
2015-11-19 17:43:47 +00:00
isp_pdb_add_update ( isp , chan , & pdb ) ;
2006-11-02 03:21:32 +00:00
continue ;
}
2015-11-19 17:43:47 +00:00
relogin :
2015-11-21 21:01:00 +00:00
if ( ( fcp - > role & ISP_ROLE_INITIATOR ) = = 0 ) {
isp_prt ( isp , ISP_LOG_SANCFG ,
" Chan %d Port 0x%06x is not logged in " , chan , portid ) ;
2015-07-13 15:11:05 +00:00
continue ;
2015-11-21 21:01:00 +00:00
}
2015-07-13 15:11:05 +00:00
2017-07-03 15:56:45 +00:00
r = isp_gff_id ( isp , chan , portid ) ;
if ( r = = 0 ) {
isp_prt ( isp , ISP_LOG_SANCFG ,
" Chan %d Port 0x%06x is not an FCP target " , chan , portid ) ;
continue ;
}
if ( r < 0 )
r = isp_gft_id ( isp , chan , portid ) ;
if ( r = = 0 ) {
isp_prt ( isp , ISP_LOG_SANCFG ,
" Chan %d Port 0x%06x is not FCP " , chan , portid ) ;
continue ;
}
2015-10-27 18:32:03 +00:00
if ( isp_login_device ( isp , chan , portid , & pdb ,
& FCPARAM ( isp , 0 ) - > isp_lasthdl ) ) {
2015-11-19 17:43:47 +00:00
if ( fcp - > isp_loopstate < LOOP_SCANNING_FABRIC )
2015-11-17 16:33:46 +00:00
goto abort ;
2002-04-04 23:46:01 +00:00
continue ;
}
2015-11-19 17:43:47 +00:00
isp_pdb_add_update ( isp , chan , & pdb ) ;
2006-11-02 03:21:32 +00:00
}
2015-11-19 17:43:47 +00:00
if ( fcp - > isp_loopstate < LOOP_SCANNING_FABRIC )
2015-11-17 16:33:46 +00:00
goto abort ;
2006-11-02 03:21:32 +00:00
fcp - > isp_loopstate = LOOP_FSCAN_DONE ;
2015-11-17 16:33:46 +00:00
isp_prt ( isp , ISP_LOG_SANCFG , " Chan %d FC fabric scan done " , chan ) ;
2006-11-02 03:21:32 +00:00
return ( 0 ) ;
}
/*
* Find an unused handle and try and use to login to a port .
*/
static int
2010-02-18 18:35:09 +00:00
isp_login_device ( ispsoftc_t * isp , int chan , uint32_t portid , isp_pdb_t * p , uint16_t * ohp )
2006-11-02 03:21:32 +00:00
{
2020-11-20 01:15:48 +00:00
int i , r ;
2006-11-02 03:21:32 +00:00
uint16_t handle ;
2015-10-27 18:32:03 +00:00
handle = isp_next_handle ( isp , ohp ) ;
2020-11-20 01:15:48 +00:00
for ( i = 0 ; i < NPH_MAX_2K ; i + + ) {
2015-11-19 17:43:47 +00:00
if ( FCPARAM ( isp , chan ) - > isp_loopstate ! = LOOP_SCANNING_FABRIC )
return ( - 1 ) ;
/* Check if this handle is free. */
2015-12-27 06:28:31 +00:00
r = isp_getpdb ( isp , chan , handle , p ) ;
2015-11-19 17:43:47 +00:00
if ( r = = 0 ) {
if ( p - > portid ! = portid ) {
/* This handle is busy, try next one. */
handle = isp_next_handle ( isp , ohp ) ;
continue ;
}
2006-11-02 03:21:32 +00:00
break ;
2002-04-16 19:55:35 +00:00
}
2015-11-19 17:43:47 +00:00
if ( FCPARAM ( isp , chan ) - > isp_loopstate ! = LOOP_SCANNING_FABRIC )
2002-04-16 19:55:35 +00:00
return ( - 1 ) ;
2015-11-19 17:43:47 +00:00
2002-04-04 23:46:01 +00:00
/*
2006-11-02 03:21:32 +00:00
* Now try and log into the device
2002-04-04 23:46:01 +00:00
*/
2015-12-26 06:13:01 +00:00
r = isp_plogx ( isp , chan , handle , portid , PLOGX_FLG_CMD_PLOGI ) ;
2006-11-18 03:53:16 +00:00
if ( r = = 0 ) {
2006-11-02 03:21:32 +00:00
break ;
2006-11-18 03:53:16 +00:00
} else if ( ( r & 0xffff ) = = MBOX_PORT_ID_USED ) {
2010-02-18 18:35:09 +00:00
/*
* If we get here , then the firmwware still thinks we ' re logged into this device , but with a different
* handle . We need to break that association . We used to try and just substitute the handle , but then
* failed to get any data via isp_getpdb ( below ) .
*/
2015-12-26 06:13:01 +00:00
if ( isp_plogx ( isp , chan , r > > 16 , portid , PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL ) ) {
2010-02-18 18:35:09 +00:00
isp_prt ( isp , ISP_LOGERR , " baw... logout of %x failed " , r > > 16 ) ;
}
2015-11-19 17:43:47 +00:00
if ( FCPARAM ( isp , chan ) - > isp_loopstate ! = LOOP_SCANNING_FABRIC )
2010-02-18 18:35:09 +00:00
return ( - 1 ) ;
2015-12-26 06:13:01 +00:00
r = isp_plogx ( isp , chan , handle , portid , PLOGX_FLG_CMD_PLOGI ) ;
2015-10-27 18:32:03 +00:00
if ( r ! = 0 )
2020-11-20 01:15:48 +00:00
i = NPH_MAX_2K ;
2006-11-02 03:21:32 +00:00
break ;
2010-06-02 23:31:27 +00:00
} else if ( ( r & 0xffff ) = = MBOX_LOOP_ID_USED ) {
2015-11-18 11:14:59 +00:00
/* Try the next handle. */
2015-10-27 18:32:03 +00:00
handle = isp_next_handle ( isp , ohp ) ;
2010-06-02 23:31:27 +00:00
} else {
2015-10-27 18:32:03 +00:00
/* Give up. */
2020-11-20 01:15:48 +00:00
i = NPH_MAX_2K ;
2006-11-02 03:21:32 +00:00
break ;
2002-04-04 23:46:01 +00:00
}
2006-11-02 03:21:32 +00:00
}
2002-04-04 23:46:01 +00:00
2020-11-20 01:15:48 +00:00
if ( i = = NPH_MAX_2K ) {
2010-02-18 18:35:09 +00:00
isp_prt ( isp , ISP_LOGWARN , " Chan %d PLOGI 0x%06x failed " , chan , portid ) ;
2006-11-02 03:21:32 +00:00
return ( - 1 ) ;
}
2002-04-04 23:46:01 +00:00
/*
2006-11-02 03:21:32 +00:00
* If we successfully logged into it , get the PDB for it
* so we can crosscheck that it is still what we think it
* is and that we also have the role it plays
2002-04-04 23:46:01 +00:00
*/
2015-12-27 06:28:31 +00:00
r = isp_getpdb ( isp , chan , handle , p ) ;
2006-11-02 03:21:32 +00:00
if ( r ! = 0 ) {
2010-02-18 18:35:09 +00:00
isp_prt ( isp , ISP_LOGERR , " Chan %d new device 0x%06x@0x%x disappeared " , chan , portid , handle ) ;
2006-11-02 03:21:32 +00:00
return ( - 1 ) ;
2002-04-04 23:46:01 +00:00
}
2006-11-02 03:21:32 +00:00
if ( p - > handle ! = handle | | p - > portid ! = portid ) {
2010-02-18 18:35:09 +00:00
isp_prt ( isp , ISP_LOGERR , " Chan %d new device 0x%06x@0x%x changed (0x%06x@0x%0x) " ,
2009-08-01 01:04:26 +00:00
chan , portid , handle , p - > portid , p - > handle ) ;
2006-11-02 03:21:32 +00:00
return ( - 1 ) ;
}
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
return ( 0 ) ;
}
2001-01-09 02:46:23 +00:00
2006-11-02 03:21:32 +00:00
static int
2009-08-01 01:04:26 +00:00
isp_register_fc4_type ( ispsoftc_t * isp , int chan )
2001-01-09 02:46:23 +00:00
{
2009-08-01 01:04:26 +00:00
fcparam * fcp = FCPARAM ( isp , chan ) ;
2017-07-02 14:59:41 +00:00
rft_id_t rp ;
ct_hdr_t * ct = & rp . rftid_hdr ;
2006-11-02 03:21:32 +00:00
uint8_t * scp = fcp - > isp_scratch ;
2009-08-01 01:04:26 +00:00
if ( FC_SCRATCH_ACQUIRE ( isp , chan ) ) {
isp_prt ( isp , ISP_LOGERR , sacq ) ;
return ( - 1 ) ;
}
2020-11-20 01:15:48 +00:00
/* Build the CT command and execute via pass-through. */
ISP_MEMZERO ( & rp , sizeof ( rp ) ) ;
ct - > ct_revision = CT_REVISION ;
ct - > ct_fcs_type = CT_FC_TYPE_FC ;
ct - > ct_fcs_subtype = CT_FC_SUBTYPE_NS ;
ct - > ct_cmd_resp = SNS_RFT_ID ;
ct - > ct_bcnt_resid = ( sizeof ( rft_id_t ) - sizeof ( ct_hdr_t ) ) > > 2 ;
rp . rftid_portid [ 0 ] = fcp - > isp_portid > > 16 ;
rp . rftid_portid [ 1 ] = fcp - > isp_portid > > 8 ;
rp . rftid_portid [ 2 ] = fcp - > isp_portid ;
rp . rftid_fc4types [ FC4_SCSI > > 5 ] = 1 < < ( FC4_SCSI & 0x1f ) ;
isp_put_rft_id ( isp , & rp , ( rft_id_t * ) scp ) ;
if ( isp_ct_passthru ( isp , chan , sizeof ( rft_id_t ) , sizeof ( ct_hdr_t ) ) ) {
FC_SCRATCH_RELEASE ( isp , chan ) ;
return ( - 1 ) ;
2006-11-02 03:21:32 +00:00
}
2015-12-27 06:28:31 +00:00
isp_get_ct_hdr ( isp , ( ct_hdr_t * ) scp , ct ) ;
2009-08-01 01:04:26 +00:00
FC_SCRATCH_RELEASE ( isp , chan ) ;
2006-11-02 03:21:32 +00:00
if ( ct - > ct_cmd_resp = = LS_RJT ) {
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
isp_prt ( isp , ISP_LOG_SANCFG | ISP_LOG_WARN1 , " Chan %d Register FC4 Type rejected " , chan ) ;
2006-11-02 03:21:32 +00:00
return ( - 1 ) ;
} else if ( ct - > ct_cmd_resp = = LS_ACC ) {
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
isp_prt ( isp , ISP_LOG_SANCFG , " Chan %d Register FC4 Type accepted " , chan ) ;
2006-11-02 03:21:32 +00:00
} else {
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
isp_prt ( isp , ISP_LOGWARN , " Chan %d Register FC4 Type: 0x%x " , chan , ct - > ct_cmd_resp ) ;
2006-11-02 03:21:32 +00:00
return ( - 1 ) ;
}
2016-04-09 11:54:09 +00:00
return ( 0 ) ;
2006-11-02 03:21:32 +00:00
}
2015-11-17 19:57:49 +00:00
static int
isp_register_fc4_features_24xx ( ispsoftc_t * isp , int chan )
{
fcparam * fcp = FCPARAM ( isp , chan ) ;
ct_hdr_t * ct ;
2016-04-09 11:54:09 +00:00
rff_id_t rp ;
2015-11-17 19:57:49 +00:00
uint8_t * scp = fcp - > isp_scratch ;
if ( FC_SCRATCH_ACQUIRE ( isp , chan ) ) {
isp_prt ( isp , ISP_LOGERR , sacq ) ;
return ( - 1 ) ;
}
/*
* Build the CT header and command in memory .
*/
2016-04-09 11:54:09 +00:00
ISP_MEMZERO ( & rp , sizeof ( rp ) ) ;
ct = & rp . rffid_hdr ;
2015-11-17 19:57:49 +00:00
ct - > ct_revision = CT_REVISION ;
ct - > ct_fcs_type = CT_FC_TYPE_FC ;
ct - > ct_fcs_subtype = CT_FC_SUBTYPE_NS ;
ct - > ct_cmd_resp = SNS_RFF_ID ;
ct - > ct_bcnt_resid = ( sizeof ( rff_id_t ) - sizeof ( ct_hdr_t ) ) > > 2 ;
2016-04-09 11:54:09 +00:00
rp . rffid_portid [ 0 ] = fcp - > isp_portid > > 16 ;
rp . rffid_portid [ 1 ] = fcp - > isp_portid > > 8 ;
rp . rffid_portid [ 2 ] = fcp - > isp_portid ;
rp . rffid_fc4features = 0 ;
2015-11-17 19:57:49 +00:00
if ( fcp - > role & ISP_ROLE_TARGET )
2016-04-09 11:54:09 +00:00
rp . rffid_fc4features | = 1 ;
2015-11-17 19:57:49 +00:00
if ( fcp - > role & ISP_ROLE_INITIATOR )
2016-04-09 11:54:09 +00:00
rp . rffid_fc4features | = 2 ;
rp . rffid_fc4type = FC4_SCSI ;
2016-04-16 06:36:56 +00:00
isp_put_rff_id ( isp , & rp , ( rff_id_t * ) scp ) ;
2016-04-09 11:54:09 +00:00
if ( isp - > isp_dblev & ISP_LOGDEBUG1 )
2016-04-16 06:36:56 +00:00
isp_print_bytes ( isp , " CT request " , sizeof ( rft_id_t ) , scp ) ;
2015-11-17 19:57:49 +00:00
2016-04-09 11:54:09 +00:00
if ( isp_ct_passthru ( isp , chan , sizeof ( rft_id_t ) , sizeof ( ct_hdr_t ) ) ) {
2015-11-17 19:57:49 +00:00
FC_SCRATCH_RELEASE ( isp , chan ) ;
return ( - 1 ) ;
}
2015-12-27 06:28:31 +00:00
isp_get_ct_hdr ( isp , ( ct_hdr_t * ) scp , ct ) ;
2015-11-17 19:57:49 +00:00
FC_SCRATCH_RELEASE ( isp , chan ) ;
if ( ct - > ct_cmd_resp = = LS_RJT ) {
isp_prt ( isp , ISP_LOG_SANCFG | ISP_LOG_WARN1 ,
" Chan %d Register FC4 Features rejected " , chan ) ;
return ( - 1 ) ;
} else if ( ct - > ct_cmd_resp = = LS_ACC ) {
isp_prt ( isp , ISP_LOG_SANCFG ,
" Chan %d Register FC4 Features accepted " , chan ) ;
} else {
isp_prt ( isp , ISP_LOGWARN ,
" Chan %d Register FC4 Features: 0x%x " , chan , ct - > ct_cmd_resp ) ;
return ( - 1 ) ;
}
2016-04-09 11:54:09 +00:00
return ( 0 ) ;
2015-11-17 19:57:49 +00:00
}
2016-04-09 14:50:47 +00:00
static int
isp_register_port_name_24xx ( ispsoftc_t * isp , int chan )
{
fcparam * fcp = FCPARAM ( isp , chan ) ;
ct_hdr_t * ct ;
rspn_id_t rp ;
uint8_t * scp = fcp - > isp_scratch ;
int len ;
if ( FC_SCRATCH_ACQUIRE ( isp , chan ) ) {
isp_prt ( isp , ISP_LOGERR , sacq ) ;
return ( - 1 ) ;
}
/*
* Build the CT header and command in memory .
*/
ISP_MEMZERO ( & rp , sizeof ( rp ) ) ;
ct = & rp . rspnid_hdr ;
ct - > ct_revision = CT_REVISION ;
ct - > ct_fcs_type = CT_FC_TYPE_FC ;
ct - > ct_fcs_subtype = CT_FC_SUBTYPE_NS ;
ct - > ct_cmd_resp = SNS_RSPN_ID ;
rp . rspnid_portid [ 0 ] = fcp - > isp_portid > > 16 ;
rp . rspnid_portid [ 1 ] = fcp - > isp_portid > > 8 ;
rp . rspnid_portid [ 2 ] = fcp - > isp_portid ;
rp . rspnid_length = 0 ;
len = offsetof ( rspn_id_t , rspnid_name ) ;
mtx_lock ( & prison0 . pr_mtx ) ;
2016-04-16 06:36:56 +00:00
rp . rspnid_length + = sprintf ( & scp [ len + rp . rspnid_length ] ,
2016-04-09 14:50:47 +00:00
" %s " , prison0 . pr_hostname [ 0 ] ? prison0 . pr_hostname : " FreeBSD " ) ;
mtx_unlock ( & prison0 . pr_mtx ) ;
2016-04-16 06:36:56 +00:00
rp . rspnid_length + = sprintf ( & scp [ len + rp . rspnid_length ] ,
2016-04-09 14:50:47 +00:00
" :%s " , device_get_nameunit ( isp - > isp_dev ) ) ;
if ( chan ! = 0 ) {
2016-04-16 06:36:56 +00:00
rp . rspnid_length + = sprintf ( & scp [ len + rp . rspnid_length ] ,
" /%d " , chan ) ;
2016-04-09 14:50:47 +00:00
}
len + = rp . rspnid_length ;
ct - > ct_bcnt_resid = ( len - sizeof ( ct_hdr_t ) ) > > 2 ;
2016-04-16 06:36:56 +00:00
isp_put_rspn_id ( isp , & rp , ( rspn_id_t * ) scp ) ;
2016-04-09 14:50:47 +00:00
if ( isp_ct_passthru ( isp , chan , len , sizeof ( ct_hdr_t ) ) ) {
FC_SCRATCH_RELEASE ( isp , chan ) ;
return ( - 1 ) ;
}
isp_get_ct_hdr ( isp , ( ct_hdr_t * ) scp , ct ) ;
FC_SCRATCH_RELEASE ( isp , chan ) ;
if ( ct - > ct_cmd_resp = = LS_RJT ) {
isp_prt ( isp , ISP_LOG_SANCFG | ISP_LOG_WARN1 ,
" Chan %d Register Symbolic Port Name rejected " , chan ) ;
return ( - 1 ) ;
} else if ( ct - > ct_cmd_resp = = LS_ACC ) {
isp_prt ( isp , ISP_LOG_SANCFG ,
" Chan %d Register Symbolic Port Name accepted " , chan ) ;
} else {
isp_prt ( isp , ISP_LOGWARN ,
" Chan %d Register Symbolic Port Name: 0x%x " , chan , ct - > ct_cmd_resp ) ;
return ( - 1 ) ;
}
return ( 0 ) ;
}
static int
isp_register_node_name_24xx ( ispsoftc_t * isp , int chan )
{
fcparam * fcp = FCPARAM ( isp , chan ) ;
ct_hdr_t * ct ;
rsnn_nn_t rp ;
uint8_t * scp = fcp - > isp_scratch ;
int len ;
if ( FC_SCRATCH_ACQUIRE ( isp , chan ) ) {
isp_prt ( isp , ISP_LOGERR , sacq ) ;
return ( - 1 ) ;
}
/*
* Build the CT header and command in memory .
*/
ISP_MEMZERO ( & rp , sizeof ( rp ) ) ;
ct = & rp . rsnnnn_hdr ;
ct - > ct_revision = CT_REVISION ;
ct - > ct_fcs_type = CT_FC_TYPE_FC ;
ct - > ct_fcs_subtype = CT_FC_SUBTYPE_NS ;
ct - > ct_cmd_resp = SNS_RSNN_NN ;
MAKE_NODE_NAME_FROM_WWN ( rp . rsnnnn_nodename , fcp - > isp_wwnn ) ;
rp . rsnnnn_length = 0 ;
len = offsetof ( rsnn_nn_t , rsnnnn_name ) ;
mtx_lock ( & prison0 . pr_mtx ) ;
2016-04-16 06:36:56 +00:00
rp . rsnnnn_length + = sprintf ( & scp [ len + rp . rsnnnn_length ] ,
2016-04-09 14:50:47 +00:00
" %s " , prison0 . pr_hostname [ 0 ] ? prison0 . pr_hostname : " FreeBSD " ) ;
mtx_unlock ( & prison0 . pr_mtx ) ;
len + = rp . rsnnnn_length ;
ct - > ct_bcnt_resid = ( len - sizeof ( ct_hdr_t ) ) > > 2 ;
2016-04-16 06:36:56 +00:00
isp_put_rsnn_nn ( isp , & rp , ( rsnn_nn_t * ) scp ) ;
2016-04-09 14:50:47 +00:00
if ( isp_ct_passthru ( isp , chan , len , sizeof ( ct_hdr_t ) ) ) {
FC_SCRATCH_RELEASE ( isp , chan ) ;
return ( - 1 ) ;
}
isp_get_ct_hdr ( isp , ( ct_hdr_t * ) scp , ct ) ;
FC_SCRATCH_RELEASE ( isp , chan ) ;
if ( ct - > ct_cmd_resp = = LS_RJT ) {
isp_prt ( isp , ISP_LOG_SANCFG | ISP_LOG_WARN1 ,
" Chan %d Register Symbolic Node Name rejected " , chan ) ;
return ( - 1 ) ;
} else if ( ct - > ct_cmd_resp = = LS_ACC ) {
isp_prt ( isp , ISP_LOG_SANCFG ,
" Chan %d Register Symbolic Node Name accepted " , chan ) ;
} else {
isp_prt ( isp , ISP_LOGWARN ,
" Chan %d Register Symbolic Node Name: 0x%x " , chan , ct - > ct_cmd_resp ) ;
return ( - 1 ) ;
}
return ( 0 ) ;
}
2006-11-02 03:21:32 +00:00
static uint16_t
2015-10-27 18:32:03 +00:00
isp_next_handle ( ispsoftc_t * isp , uint16_t * ohp )
2006-11-02 03:21:32 +00:00
{
2015-10-27 18:32:03 +00:00
fcparam * fcp ;
int i , chan , wrap ;
2020-11-20 01:15:48 +00:00
uint16_t handle ;
2015-10-27 18:32:03 +00:00
handle = * ohp ;
wrap = 0 ;
next :
2006-12-05 07:50:23 +00:00
if ( handle = = NIL_HANDLE ) {
2020-11-20 01:15:48 +00:00
handle = 0 ;
2006-11-02 03:21:32 +00:00
} else {
2015-10-27 18:32:03 +00:00
handle + + ;
2020-11-20 01:15:48 +00:00
if ( handle > NPH_RESERVED - 1 ) {
2015-10-27 18:32:03 +00:00
if ( + + wrap > = 2 ) {
isp_prt ( isp , ISP_LOGERR , " Out of port handles! " ) ;
return ( NIL_HANDLE ) ;
2006-11-02 03:21:32 +00:00
}
2020-11-20 01:15:48 +00:00
handle = 0 ;
2006-11-02 03:21:32 +00:00
}
}
2015-10-27 18:32:03 +00:00
for ( chan = 0 ; chan < isp - > isp_nchan ; chan + + ) {
fcp = FCPARAM ( isp , chan ) ;
if ( fcp - > role = = ISP_ROLE_NONE )
2007-01-20 04:00:21 +00:00
continue ;
2015-10-27 18:32:03 +00:00
for ( i = 0 ; i < MAX_FC_TARG ; i + + ) {
if ( fcp - > portdb [ i ] . state ! = FC_PORTDB_STATE_NIL & &
fcp - > portdb [ i ] . handle = = handle )
goto next ;
2007-01-20 04:00:21 +00:00
}
}
2015-10-27 18:32:03 +00:00
* ohp = handle ;
2007-01-20 04:00:21 +00:00
return ( handle ) ;
2001-01-09 02:46:23 +00:00
}
2001-02-11 03:44:43 +00:00
1998-04-22 17:54:58 +00:00
/*
1998-09-15 08:42:56 +00:00
* Start a command . Locking is assumed done in the caller .
1998-04-22 17:54:58 +00:00
*/
1998-09-15 08:42:56 +00:00
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
int
2001-03-14 04:11:56 +00:00
isp_start ( XS_T * xs )
1998-04-22 17:54:58 +00:00
{
2006-04-21 18:30:01 +00:00
ispsoftc_t * isp ;
2020-11-20 01:15:48 +00:00
fcparam * fcp ;
2015-12-25 13:03:18 +00:00
uint32_t cdblen ;
2020-11-20 01:15:48 +00:00
ispreqt7_t local , * reqp = & local ;
void * qep ;
2015-07-05 02:09:46 +00:00
fcportdb_t * lp ;
int target , dmaresult ;
1998-04-22 17:54:58 +00:00
XS_INITERR ( xs ) ;
isp = XS_ISP ( xs ) ;
1998-09-15 08:42:56 +00:00
/*
2000-02-15 00:35:00 +00:00
* Check command CDB length , etc . . We really are limited to 16 bytes
* for Fibre Channel , but can do up to 44 bytes in parallel SCSI ,
* but probably only if we ' re running fairly new firmware ( we ' ll
* let the old f / w choke on an extended command queue entry ) .
1998-09-15 08:42:56 +00:00
*/
1999-03-17 05:04:39 +00:00
2020-11-20 01:15:48 +00:00
if ( XS_CDBLEN ( xs ) > 16 | | XS_CDBLEN ( xs ) = = 0 ) {
2009-08-01 01:04:26 +00:00
isp_prt ( isp , ISP_LOGERR , " unsupported cdb length (%d, CDB[0]=0x%x) " , XS_CDBLEN ( xs ) , XS_CDBP ( xs ) [ 0 ] & 0xff ) ;
2017-02-26 14:29:09 +00:00
XS_SETERR ( xs , HBA_REQINVAL ) ;
1998-09-15 08:42:56 +00:00
return ( CMD_COMPLETE ) ;
}
/*
2006-11-02 03:21:32 +00:00
* Translate the target to device handle as appropriate , checking
* for correct device state as well .
1999-03-17 05:04:39 +00:00
*/
Roll revision levels. Add support for the Qlogic 2200 (warn about
not having SCSI_ISP_SCCLUN config defined if we don't have f/w for
the 2200- it's resident firmware uses SCCLUN (65535 luns)). Change
the way the default LoopID is gathered (it's now a platform specific
define so that some attempt at a synthetic WWN can be made in case
NVRAM isn't readable).
Change initialization of options a bit- don't use ADISC. Set
FullDuplex mode if config options tells us to do so. Do not use
FULL_LOGIN after LIP- it's the right thing to do but it causes too
much loop disruption (Loop Resets). Sanity check some default
values. Redo construction of port and node WWNs based upon what we
have- if we have 2 in the top nibble, we can have distinct port
and node WWNs. Clean up some SCCLUN related code that we obviously
had never compiled (:-(). Audit commands coming int ispscsicmd and
don't throw commands at Fibre devices that do not have Class 3
service parameters TARGET ROLE defined.
Clean up f/w initialization a bit. Add Fabric support (or at least
the first blush of it). Whew - way too much to describe here.
Basically, after a LIP, hang out until we see a Loop Up or a Port
DataBase Change async event, then see if we're on a Fabric
(GET_PORT_NAME of FL_PORT_ID). If we are, try and scan the fabric
controller for fabric devices using the GetAllNext SNS subcommand.
As we find devices, announce them to the outer layer. Try and do
some guard code for broken (Brocade) SNS servers (that get stuck
in loops- gotta maybe do this a different way using the GP_ID3 cmd
instead). Then do a scan of the lower (local loop) ids using a
GET_PORT_NAME to see if the f/w has logged into anything at that
loop id. If so, then do a GET_PORT_DATABASE command. Do this scan
into a local database. At this point we can say the loop is 'Ready'.
After this, we merge our local loop port database with our stored
port database- in a as yet to be really fully exercised fashion we
try and follow the logic of something having moved around. The
first time we see something at a Loop ID, we fix it, for the purpose
of this system instance, at that Loop ID. If things shift around
so it ends up somewhere else, we still keep it at this Loop ID (our
'Target') but use the new (moved) Loop ID when we actually throw
commands at it. Check for insane cases of different Loop IDs both
claiming to have the same WWN- if that happens, invalidate both.
Notify the outer layer of devices that have arrived and devices
that have gone away. *Finally*, when this is done, search the
softc's database of Fabric devices and perform logout/login actions.
The Qlogic f/w maintains logout/login for all local loop devices.
We have to maintain logout/login for fabric devices- total PITA.
Expect to see this area undergo more change over time.
1999-07-02 23:06:38 +00:00
target = XS_TGT ( xs ) ;
2020-11-20 01:15:48 +00:00
fcp = FCPARAM ( isp , XS_CHANNEL ( xs ) ) ;
2006-11-02 03:21:32 +00:00
2020-11-20 01:15:48 +00:00
if ( ( fcp - > role & ISP_ROLE_INITIATOR ) = = 0 ) {
isp_prt ( isp , ISP_LOG_WARN1 ,
" %d.%d.%jx I am not an initiator " ,
XS_CHANNEL ( xs ) , target , ( uintmax_t ) XS_LUN ( xs ) ) ;
XS_SETERR ( xs , HBA_SELTIMEOUT ) ;
return ( CMD_COMPLETE ) ;
}
2015-10-25 10:49:05 +00:00
2020-11-20 01:15:48 +00:00
if ( isp - > isp_state ! = ISP_RUNSTATE ) {
isp_prt ( isp , ISP_LOGERR , " Adapter not at RUNSTATE " ) ;
XS_SETERR ( xs , HBA_BOTCH ) ;
return ( CMD_COMPLETE ) ;
}
2015-10-25 10:49:05 +00:00
2020-11-20 01:15:48 +00:00
isp_prt ( isp , ISP_LOGDEBUG2 , " XS_TGT(xs)=%d " , target ) ;
lp = & fcp - > portdb [ target ] ;
if ( target < 0 | | target > = MAX_FC_TARG | |
lp - > is_target = = 0 ) {
XS_SETERR ( xs , HBA_SELTIMEOUT ) ;
return ( CMD_COMPLETE ) ;
}
if ( fcp - > isp_loopstate ! = LOOP_READY ) {
isp_prt ( isp , ISP_LOGDEBUG1 ,
" %d.%d.%jx loop is not ready " ,
XS_CHANNEL ( xs ) , target , ( uintmax_t ) XS_LUN ( xs ) ) ;
return ( CMD_RQLATER ) ;
}
if ( lp - > state = = FC_PORTDB_STATE_ZOMBIE ) {
isp_prt ( isp , ISP_LOGDEBUG1 ,
" %d.%d.%jx target zombie " ,
XS_CHANNEL ( xs ) , target , ( uintmax_t ) XS_LUN ( xs ) ) ;
return ( CMD_RQLATER ) ;
}
if ( lp - > state ! = FC_PORTDB_STATE_VALID ) {
isp_prt ( isp , ISP_LOGDEBUG1 ,
" %d.%d.%jx bad db port state 0x%x " ,
XS_CHANNEL ( xs ) , target , ( uintmax_t ) XS_LUN ( xs ) , lp - > state ) ;
XS_SETERR ( xs , HBA_SELTIMEOUT ) ;
return ( CMD_COMPLETE ) ;
1998-04-22 17:54:58 +00:00
}
1998-09-15 08:42:56 +00:00
2006-11-02 03:21:32 +00:00
start_again :
2009-08-01 01:04:26 +00:00
qep = isp_getrqentry ( isp ) ;
if ( qep = = NULL ) {
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
isp_prt ( isp , ISP_LOG_WARN1 , " Request Queue Overflow " ) ;
1998-04-22 17:54:58 +00:00
XS_SETERR ( xs , HBA_BOTCH ) ;
return ( CMD_EAGAIN ) ;
}
2009-08-01 01:04:26 +00:00
XS_SETERR ( xs , HBA_NOERROR ) ;
1998-04-22 17:54:58 +00:00
1999-05-11 05:06:55 +00:00
/*
* Now see if we need to synchronize the ISP with respect to anything .
2017-01-15 17:54:01 +00:00
* We do dual duty here ( cough ) for synchronizing for buses other
1999-05-11 05:06:55 +00:00
* than which we got here to send a command to .
*/
2020-11-20 01:15:48 +00:00
ISP_MEMZERO ( reqp , QENTRY_LEN ) ;
2009-08-01 01:04:26 +00:00
if ( ISP_TST_SENDMARKER ( isp , XS_CHANNEL ( xs ) ) ) {
2020-11-20 01:15:48 +00:00
isp_marker_24xx_t * m = ( isp_marker_24xx_t * ) reqp ;
m - > mrk_header . rqs_entry_count = 1 ;
m - > mrk_header . rqs_entry_type = RQSTYPE_MARKER ;
m - > mrk_modifier = SYNC_ALL ;
m - > mrk_vphdl = XS_CHANNEL ( xs ) ;
isp_put_marker_24xx ( isp , m , qep ) ;
2009-08-01 01:04:26 +00:00
ISP_SYNC_REQUEST ( isp ) ;
ISP_SET_SENDMARKER ( isp , XS_CHANNEL ( xs ) , 0 ) ;
goto start_again ;
1998-04-22 17:54:58 +00:00
}
2010-06-05 20:37:40 +00:00
/*
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
* NB : we do not support long CDBs ( yet )
2010-06-05 20:37:40 +00:00
*/
cdblen = XS_CDBLEN ( xs ) ;
2020-11-20 01:15:48 +00:00
if ( cdblen > sizeof ( reqp - > req_cdb ) ) {
isp_prt ( isp , ISP_LOGERR , " Command Length %u too long for this chip " , cdblen ) ;
XS_SETERR ( xs , HBA_REQINVAL ) ;
return ( CMD_COMPLETE ) ;
}
2020-11-20 18:02:04 +00:00
reqp - > req_header . rqs_entry_type = RQSTYPE_T7RQS ;
reqp - > req_header . rqs_entry_count = 1 ;
2020-11-20 01:15:48 +00:00
reqp - > req_nphdl = lp - > handle ;
2020-11-20 18:02:04 +00:00
reqp - > req_time = XS_TIME ( xs ) ;
2020-11-20 01:15:48 +00:00
be64enc ( reqp - > req_lun , CAM_EXTLUN_BYTE_SWIZZLE ( XS_LUN ( xs ) ) ) ;
2020-11-20 18:02:04 +00:00
if ( XS_XFRIN ( xs ) )
reqp - > req_alen_datadir = FCP_CMND_DATA_READ ;
else if ( XS_XFROUT ( xs ) )
reqp - > req_alen_datadir = FCP_CMND_DATA_WRITE ;
if ( XS_TAG_P ( xs ) )
reqp - > req_task_attribute = XS_TAG_TYPE ( xs ) ;
else
reqp - > req_task_attribute = FCP_CMND_TASK_ATTR_SIMPLE ;
reqp - > req_task_attribute | = ( XS_PRIORITY ( xs ) < < FCP_CMND_PRIO_SHIFT ) &
FCP_CMND_PRIO_MASK ;
2020-11-20 01:15:48 +00:00
if ( FCPARAM ( isp , XS_CHANNEL ( xs ) ) - > fctape_enabled & & ( lp - > prli_word3 & PRLI_WD3_RETRY ) ) {
if ( FCP_NEXT_CRN ( isp , & reqp - > req_crn , xs ) ) {
isp_prt ( isp , ISP_LOG_WARN1 ,
" %d.%d.%jx cannot generate next CRN " ,
XS_CHANNEL ( xs ) , target , ( uintmax_t ) XS_LUN ( xs ) ) ;
XS_SETERR ( xs , HBA_BOTCH ) ;
return ( CMD_EAGAIN ) ;
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
}
1998-04-22 17:54:58 +00:00
}
2020-11-20 01:15:48 +00:00
ISP_MEMCPY ( reqp - > req_cdb , XS_CDBP ( xs ) , cdblen ) ;
2020-11-20 18:02:04 +00:00
reqp - > req_dl = XS_XFRLEN ( xs ) ;
reqp - > req_tidlo = lp - > portid ;
reqp - > req_tidhi = lp - > portid > > 16 ;
reqp - > req_vpidx = ISP_GET_VPIDX ( isp , XS_CHANNEL ( xs ) ) ;
1998-04-22 17:54:58 +00:00
2015-12-25 13:03:18 +00:00
/* Whew. Thankfully the same for type 7 requests */
reqp - > req_handle = isp_allocate_handle ( isp , xs , ISP_HANDLE_INITIATOR ) ;
if ( reqp - > req_handle = = 0 ) {
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
isp_prt ( isp , ISP_LOG_WARN1 , " out of xflist pointers " ) ;
1999-10-17 18:58:22 +00:00
XS_SETERR ( xs , HBA_BOTCH ) ;
return ( CMD_EAGAIN ) ;
}
Major restructuring for swizzling to the request queue and unswizzling from
the response queue. Instead of the ad hoc ISP_SWIZZLE_REQUEST, we now have
a complete set of inline functions in isp_inline.h. Each platform is
responsible for providing just one of a set of ISP_IOX_{GET,PUT}{8,16,32}
macros.
The reason this needs to be done is that we need to have a single set of
functions that will work correctly on multiple architectures for both little
and big endian machines. It also needs to work correctly in the case that
we have the request or response queues in memory that has to be treated
specially (e.g., have ddi_dma_sync called on it for Solaris after we update
it or before we read from it). It also has to handle the SBus cards (for
platforms that have them) which, while on a Big Endian machine, do *not*
require *most* of the request/response queue entry fields to be swizzled
or unswizzled.
One thing that falls out of this is that we no longer build requests in the
request queue itself. Instead, we build the request locally (e.g., on the
stack) and then as part of the swizzling operation, copy it to the request
queue entry we've allocated. I thought long and hard about whether this was
too expensive a change to make as it in a lot of cases requires an extra
copy. On balance, the flexbility is worth it. With any luck, the entry that
we build locally stays in a processor writeback cache (after all, it's only
64 bytes) so that the cost of actually flushing it to the memory area that is
the shared queue with the PCI device is not all that expensive. We may examine
this again and try to get clever in the future to try and avoid copies.
Another change that falls out of this is that MEMORYBARRIER should be taken
a lot more seriously. The macro ISP_ADD_REQUEST does a MEMORYBARRIER on the
entry being added. But there had been many other places this had been missing.
It's now very important that it be done.
Additional changes:
Fix a longstanding buglet of sorts. When we get an entry via isp_getrqentry,
the iptr value that gets returned is the value we intend to eventually plug
into the ISP registers as the entry *one past* the last one we've written-
*not* the current entry we're updating. All along we've been calling sync
functions on the wrong index value. Argh. The 'fix' here is to rename all
'iptr' variables as 'nxti' to remember that this is the 'next' pointer-
not the current pointer.
Devote a single bit to mboxbsy- and set aside bits for output mbox registers
that we need to pick up- we can have at least one command which does not
have any defined output registers (MBOX_EXECUTE_FIRMWARE).
MFC after: 2 weeks
2001-12-11 00:18:45 +00:00
1999-10-17 18:58:22 +00:00
/*
2009-08-01 01:04:26 +00:00
* Set up DMA and / or do any platform dependent swizzling of the request entry
1999-10-17 18:58:22 +00:00
* so that the Qlogic F / W understands what is being asked of it .
2009-08-01 01:04:26 +00:00
*
* The callee is responsible for adding all requests at this point .
Major restructuring for swizzling to the request queue and unswizzling from
the response queue. Instead of the ad hoc ISP_SWIZZLE_REQUEST, we now have
a complete set of inline functions in isp_inline.h. Each platform is
responsible for providing just one of a set of ISP_IOX_{GET,PUT}{8,16,32}
macros.
The reason this needs to be done is that we need to have a single set of
functions that will work correctly on multiple architectures for both little
and big endian machines. It also needs to work correctly in the case that
we have the request or response queues in memory that has to be treated
specially (e.g., have ddi_dma_sync called on it for Solaris after we update
it or before we read from it). It also has to handle the SBus cards (for
platforms that have them) which, while on a Big Endian machine, do *not*
require *most* of the request/response queue entry fields to be swizzled
or unswizzled.
One thing that falls out of this is that we no longer build requests in the
request queue itself. Instead, we build the request locally (e.g., on the
stack) and then as part of the swizzling operation, copy it to the request
queue entry we've allocated. I thought long and hard about whether this was
too expensive a change to make as it in a lot of cases requires an extra
copy. On balance, the flexbility is worth it. With any luck, the entry that
we build locally stays in a processor writeback cache (after all, it's only
64 bytes) so that the cost of actually flushing it to the memory area that is
the shared queue with the PCI device is not all that expensive. We may examine
this again and try to get clever in the future to try and avoid copies.
Another change that falls out of this is that MEMORYBARRIER should be taken
a lot more seriously. The macro ISP_ADD_REQUEST does a MEMORYBARRIER on the
entry being added. But there had been many other places this had been missing.
It's now very important that it be done.
Additional changes:
Fix a longstanding buglet of sorts. When we get an entry via isp_getrqentry,
the iptr value that gets returned is the value we intend to eventually plug
into the ISP registers as the entry *one past* the last one we've written-
*not* the current entry we're updating. All along we've been calling sync
functions on the wrong index value. Argh. The 'fix' here is to rename all
'iptr' variables as 'nxti' to remember that this is the 'next' pointer-
not the current pointer.
Devote a single bit to mboxbsy- and set aside bits for output mbox registers
that we need to pick up- we can have at least one command which does not
have any defined output registers (MBOX_EXECUTE_FIRMWARE).
MFC after: 2 weeks
2001-12-11 00:18:45 +00:00
*/
2009-08-01 01:04:26 +00:00
dmaresult = ISP_DMASETUP ( isp , xs , reqp ) ;
2020-11-20 18:02:04 +00:00
if ( dmaresult ! = 0 ) {
2015-12-25 13:03:18 +00:00
isp_destroy_handle ( isp , reqp - > req_handle ) ;
1998-09-17 21:03:45 +00:00
/*
* dmasetup sets actual error in packet , and
* return what we were given to return .
*/
2009-08-01 01:04:26 +00:00
return ( dmaresult ) ;
1998-04-22 17:54:58 +00:00
}
2010-03-26 15:13:31 +00:00
isp_xs_prt ( isp , xs , ISP_LOGDEBUG0 , " START cmd cdb[0]=0x%x datalen %ld " , XS_CDBP ( xs ) [ 0 ] , ( long ) XS_XFRLEN ( xs ) ) ;
2020-11-20 18:02:04 +00:00
return ( 0 ) ;
1998-04-22 17:54:58 +00:00
}
/*
1998-09-15 08:42:56 +00:00
* isp control
* Locks ( ints blocked ) assumed held .
1998-04-22 17:54:58 +00:00
*/
int
2009-08-01 01:04:26 +00:00
isp_control ( ispsoftc_t * isp , ispctl_t ctl , . . . )
1998-04-22 17:54:58 +00:00
{
2020-11-20 01:15:48 +00:00
fcparam * fcp ;
fcportdb_t * lp ;
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
XS_T * xs ;
2020-11-27 15:50:20 +00:00
mbreg_t * mbr ;
2009-08-01 01:04:26 +00:00
int chan , tgt ;
2006-11-02 03:21:32 +00:00
uint32_t handle ;
2009-08-01 01:04:26 +00:00
va_list ap ;
2020-11-20 01:15:48 +00:00
uint8_t local [ QENTRY_LEN ] ;
2006-01-23 06:23:37 +00:00
1998-09-15 08:42:56 +00:00
switch ( ctl ) {
case ISPCTL_RESET_BUS :
1999-03-17 05:04:39 +00:00
/*
* Issue a bus reset .
*/
2020-11-20 01:15:48 +00:00
isp_prt ( isp , ISP_LOGERR , " BUS RESET NOT IMPLEMENTED " ) ;
break ;
1998-09-15 08:42:56 +00:00
1999-03-25 22:52:45 +00:00
case ISPCTL_RESET_DEV :
2020-11-20 01:15:48 +00:00
{
isp24xx_tmf_t * tmf ;
isp24xx_statusreq_t * sp ;
2009-08-01 01:04:26 +00:00
va_start ( ap , ctl ) ;
chan = va_arg ( ap , int ) ;
tgt = va_arg ( ap , int ) ;
va_end ( ap ) ;
2020-11-20 01:15:48 +00:00
fcp = FCPARAM ( isp , chan ) ;
2016-04-12 14:19:19 +00:00
2020-11-20 01:15:48 +00:00
if ( tgt < 0 | | tgt > = MAX_FC_TARG ) {
isp_prt ( isp , ISP_LOGWARN , " Chan %d trying to reset bad target %d " , chan , tgt ) ;
2006-11-02 03:21:32 +00:00
break ;
2006-01-23 06:23:37 +00:00
}
2020-11-20 01:15:48 +00:00
lp = & fcp - > portdb [ tgt ] ;
if ( lp - > is_target = = 0 | | lp - > state ! = FC_PORTDB_STATE_VALID ) {
isp_prt ( isp , ISP_LOGWARN , " Chan %d abort of no longer valid target %d " , chan , tgt ) ;
1998-09-15 08:42:56 +00:00
break ;
}
2020-11-20 01:15:48 +00:00
tmf = ( isp24xx_tmf_t * ) local ;
ISP_MEMZERO ( tmf , QENTRY_LEN ) ;
tmf - > tmf_header . rqs_entry_type = RQSTYPE_TSK_MGMT ;
tmf - > tmf_header . rqs_entry_count = 1 ;
tmf - > tmf_nphdl = lp - > handle ;
tmf - > tmf_delay = 2 ;
tmf - > tmf_timeout = 4 ;
tmf - > tmf_flags = ISP24XX_TMF_TARGET_RESET ;
tmf - > tmf_tidlo = lp - > portid ;
tmf - > tmf_tidhi = lp - > portid > > 16 ;
tmf - > tmf_vpidx = ISP_GET_VPIDX ( isp , chan ) ;
fcp - > sendmarker = 1 ;
isp_prt ( isp , ISP_LOGALL , " Chan %d Reset N-Port Handle 0x%04x @ Port 0x%06x " , chan , lp - > handle , lp - > portid ) ;
sp = ( isp24xx_statusreq_t * ) local ;
2020-11-27 15:50:20 +00:00
if ( isp_exec_entry_mbox ( isp , tmf , sp , 2 * tmf - > tmf_timeout ) )
break ;
if ( sp - > req_completion_status = = 0 )
2020-11-20 01:15:48 +00:00
return ( 0 ) ;
isp_prt ( isp , ISP_LOGWARN , " Chan %d reset of target %d returned 0x%x " , chan , tgt , sp - > req_completion_status ) ;
break ;
}
1999-03-25 22:52:45 +00:00
case ISPCTL_ABORT_CMD :
2020-11-20 01:15:48 +00:00
{
isp24xx_abrt_t * ab = ( isp24xx_abrt_t * ) & local ;
2009-08-01 01:04:26 +00:00
va_start ( ap , ctl ) ;
xs = va_arg ( ap , XS_T * ) ;
va_end ( ap ) ;
2000-07-05 06:41:36 +00:00
tgt = XS_TGT ( xs ) ;
2009-08-01 01:04:26 +00:00
chan = XS_CHANNEL ( xs ) ;
2006-11-02 03:21:32 +00:00
1999-10-17 18:58:22 +00:00
handle = isp_find_handle ( isp , xs ) ;
if ( handle = = 0 ) {
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
isp_prt ( isp , ISP_LOGWARN , " cannot find handle for command to abort " ) ;
1998-09-15 08:42:56 +00:00
break ;
}
2016-04-12 14:19:19 +00:00
2020-11-20 01:15:48 +00:00
fcp = FCPARAM ( isp , chan ) ;
if ( tgt < 0 | | tgt > = MAX_FC_TARG ) {
isp_prt ( isp , ISP_LOGWARN , " Chan %d trying to abort bad target %d " , chan , tgt ) ;
2006-11-02 03:21:32 +00:00
break ;
1999-10-17 18:58:22 +00:00
}
2020-11-20 01:15:48 +00:00
lp = & fcp - > portdb [ tgt ] ;
if ( lp - > is_target = = 0 | | lp - > state ! = FC_PORTDB_STATE_VALID ) {
isp_prt ( isp , ISP_LOGWARN , " Chan %d abort of no longer valid target %d " , chan , tgt ) ;
2006-11-02 03:21:32 +00:00
break ;
1998-09-15 08:42:56 +00:00
}
2020-11-20 01:15:48 +00:00
isp_prt ( isp , ISP_LOGALL , " Chan %d Abort Cmd for N-Port 0x%04x @ Port 0x%06x " , chan , lp - > handle , lp - > portid ) ;
ISP_MEMZERO ( ab , QENTRY_LEN ) ;
ab - > abrt_header . rqs_entry_type = RQSTYPE_ABORT_IO ;
ab - > abrt_header . rqs_entry_count = 1 ;
ab - > abrt_handle = lp - > handle ;
ab - > abrt_cmd_handle = handle ;
ab - > abrt_tidlo = lp - > portid ;
ab - > abrt_tidhi = lp - > portid > > 16 ;
ab - > abrt_vpidx = ISP_GET_VPIDX ( isp , chan ) ;
2001-02-11 03:44:43 +00:00
2020-11-27 15:50:20 +00:00
if ( isp_exec_entry_mbox ( isp , ab , ab , 5 ) )
2020-11-20 01:15:48 +00:00
break ;
2001-02-11 03:44:43 +00:00
2020-11-27 15:50:20 +00:00
if ( ab - > abrt_nphdl = = ISP24XX_ABRT_OKAY )
2020-11-20 01:15:48 +00:00
return ( 0 ) ;
isp_prt ( isp , ISP_LOGWARN , " Chan %d handle %d abort returned 0x%x " , chan , tgt , ab - > abrt_nphdl ) ;
}
case ISPCTL_FCLINK_TEST :
{
int usdelay ;
1999-11-21 03:18:22 +00:00
2020-11-20 01:15:48 +00:00
va_start ( ap , ctl ) ;
chan = va_arg ( ap , int ) ;
usdelay = va_arg ( ap , int ) ;
va_end ( ap ) ;
if ( usdelay = = 0 )
usdelay = 250000 ;
return ( isp_fclink_test ( isp , chan , usdelay ) ) ;
}
2001-02-11 03:44:43 +00:00
case ISPCTL_SCAN_FABRIC :
2020-11-20 01:15:48 +00:00
va_start ( ap , ctl ) ;
chan = va_arg ( ap , int ) ;
va_end ( ap ) ;
return ( isp_scan_fabric ( isp , chan ) ) ;
2001-02-11 03:44:43 +00:00
case ISPCTL_SCAN_LOOP :
2020-11-20 01:15:48 +00:00
va_start ( ap , ctl ) ;
chan = va_arg ( ap , int ) ;
va_end ( ap ) ;
return ( isp_scan_loop ( isp , chan ) ) ;
2001-02-11 03:44:43 +00:00
2000-01-03 23:52:41 +00:00
case ISPCTL_PDB_SYNC :
2001-02-11 03:44:43 +00:00
2020-11-20 01:15:48 +00:00
va_start ( ap , ctl ) ;
chan = va_arg ( ap , int ) ;
va_end ( ap ) ;
return ( isp_pdb_sync ( isp , chan ) ) ;
2001-02-11 03:44:43 +00:00
case ISPCTL_SEND_LIP :
break ;
2004-02-07 03:42:17 +00:00
case ISPCTL_GET_PDB :
2020-11-20 01:15:48 +00:00
{
isp_pdb_t * pdb ;
va_start ( ap , ctl ) ;
chan = va_arg ( ap , int ) ;
tgt = va_arg ( ap , int ) ;
pdb = va_arg ( ap , isp_pdb_t * ) ;
va_end ( ap ) ;
return ( isp_getpdb ( isp , chan , tgt , pdb ) ) ;
}
2009-08-01 01:04:26 +00:00
case ISPCTL_GET_NAMES :
2006-11-02 03:21:32 +00:00
{
2009-08-01 01:04:26 +00:00
uint64_t * wwnn , * wwnp ;
va_start ( ap , ctl ) ;
chan = va_arg ( ap , int ) ;
tgt = va_arg ( ap , int ) ;
wwnn = va_arg ( ap , uint64_t * ) ;
wwnp = va_arg ( ap , uint64_t * ) ;
va_end ( ap ) ;
if ( wwnn = = NULL & & wwnp = = NULL ) {
2006-11-02 03:21:32 +00:00
break ;
}
2009-08-01 01:04:26 +00:00
if ( wwnn ) {
* wwnn = isp_get_wwn ( isp , chan , tgt , 1 ) ;
if ( * wwnn = = INI_NONE ) {
break ;
}
}
if ( wwnp ) {
* wwnp = isp_get_wwn ( isp , chan , tgt , 0 ) ;
if ( * wwnp = = INI_NONE ) {
break ;
}
}
return ( 0 ) ;
2006-11-02 03:21:32 +00:00
}
2020-11-27 15:50:20 +00:00
case ISPCTL_RUN_MBOXCMD :
{
va_start ( ap , ctl ) ;
mbr = va_arg ( ap , mbreg_t * ) ;
va_end ( ap ) ;
isp_mboxcmd ( isp , mbr ) ;
return ( 0 ) ;
}
2006-11-18 03:53:16 +00:00
case ISPCTL_PLOGX :
{
2009-08-01 01:04:26 +00:00
isp_plcmd_t * p ;
2006-12-05 07:50:23 +00:00
int r ;
2009-08-01 01:04:26 +00:00
va_start ( ap , ctl ) ;
p = va_arg ( ap , isp_plcmd_t * ) ;
va_end ( ap ) ;
if ( ( p - > flags & PLOGX_FLG_CMD_MASK ) ! = PLOGX_FLG_CMD_PLOGI | | ( p - > handle ! = NIL_HANDLE ) ) {
2015-12-26 06:13:01 +00:00
return ( isp_plogx ( isp , p - > channel , p - > handle , p - > portid , p - > flags ) ) ;
2006-12-05 07:50:23 +00:00
}
do {
2015-10-27 18:32:03 +00:00
isp_next_handle ( isp , & p - > handle ) ;
2015-12-26 06:13:01 +00:00
r = isp_plogx ( isp , p - > channel , p - > handle , p - > portid , p - > flags ) ;
2006-12-05 07:50:23 +00:00
if ( ( r & 0xffff ) = = MBOX_PORT_ID_USED ) {
p - > handle = r > > 16 ;
r = 0 ;
break ;
}
} while ( ( r & 0xffff ) = = MBOX_LOOP_ID_USED ) ;
return ( r ) ;
2006-11-18 03:53:16 +00:00
}
2015-07-04 18:38:46 +00:00
case ISPCTL_CHANGE_ROLE :
2020-11-20 01:15:48 +00:00
{
int role ;
va_start ( ap , ctl ) ;
chan = va_arg ( ap , int ) ;
role = va_arg ( ap , int ) ;
va_end ( ap ) ;
return ( isp_fc_change_role ( isp , chan , role ) ) ;
}
2009-08-01 01:04:26 +00:00
default :
isp_prt ( isp , ISP_LOGERR , " Unknown Control Opcode 0x%x " , ctl ) ;
break ;
2001-01-15 18:33:08 +00:00
1998-09-15 08:42:56 +00:00
}
return ( - 1 ) ;
}
/*
* Interrupt Service Routine ( s ) .
*
* External ( OS ) framework has done the appropriate locking ,
* and the locking will be held throughout this function .
*/
2017-03-15 14:58:29 +00:00
# ifdef ISP_TARGET_MODE
void
isp_intr_atioq ( ispsoftc_t * isp )
{
void * addr ;
uint32_t iptr , optr , oop ;
iptr = ISP_READ ( isp , BIU2400_ATIO_RSPINP ) ;
optr = isp - > isp_atioodx ;
while ( optr ! = iptr ) {
oop = optr ;
MEMORYBARRIER ( isp , SYNC_ATIOQ , oop , QENTRY_LEN , - 1 ) ;
addr = ISP_QUEUE_ENTRY ( isp - > isp_atioq , oop ) ;
2020-11-27 15:50:20 +00:00
switch ( ( ( isphdr_t * ) addr ) - > rqs_entry_type ) {
2017-03-15 14:58:29 +00:00
case RQSTYPE_NOTIFY :
case RQSTYPE_ATIO :
2020-11-20 01:15:48 +00:00
case RQSTYPE_NOTIFY_ACK : /* Can be set to ATIO queue.*/
case RQSTYPE_ABTS_RCVD : /* Can be set to ATIO queue.*/
2020-11-20 19:36:34 +00:00
( void ) isp_target_notify ( isp , addr , & oop ,
ATIO_QUEUE_LEN ( isp ) ) ;
2017-03-15 14:58:29 +00:00
break ;
2020-11-20 01:15:48 +00:00
case RQSTYPE_RPT_ID_ACQ : /* Can be set to ATIO queue.*/
2017-03-15 14:58:29 +00:00
default :
isp_print_qentry ( isp , " ?ATIOQ entry? " , oop , addr ) ;
break ;
}
2020-11-20 19:36:34 +00:00
optr = ISP_NXT_QENTRY ( oop , ATIO_QUEUE_LEN ( isp ) ) ;
2017-03-15 14:58:29 +00:00
}
if ( isp - > isp_atioodx ! = optr ) {
ISP_WRITE ( isp , BIU2400_ATIO_RSPOUTP , optr ) ;
isp - > isp_atioodx = optr ;
}
}
# endif
void
isp_intr_mbox ( ispsoftc_t * isp , uint16_t mbox0 )
{
int i , obits ;
if ( ! isp - > isp_mboxbsy ) {
isp_prt ( isp , ISP_LOGWARN , " mailbox 0x%x with no waiters " , mbox0 ) ;
return ;
}
obits = isp - > isp_obits ;
isp - > isp_mboxtmp [ 0 ] = mbox0 ;
for ( i = 1 ; i < ISP_NMBOX ( isp ) ; i + + ) {
if ( ( obits & ( 1 < < i ) ) = = 0 )
continue ;
isp - > isp_mboxtmp [ i ] = ISP_READ ( isp , MBOX_OFF ( i ) ) ;
}
2020-11-24 15:32:25 +00:00
isp - > isp_mboxbsy = 0 ;
2017-03-15 14:58:29 +00:00
}
2001-08-31 21:39:04 +00:00
void
2017-03-15 14:58:29 +00:00
isp_intr_respq ( ispsoftc_t * isp )
1998-09-15 08:42:56 +00:00
{
2017-03-22 08:56:03 +00:00
XS_T * xs , * cont_xs ;
uint8_t qe [ QENTRY_LEN ] ;
2020-11-20 01:15:48 +00:00
isp24xx_statusreq_t * sp = ( isp24xx_statusreq_t * ) qe ;
2020-11-24 17:37:12 +00:00
ispstatus_cont_t * scp = ( ispstatus_cont_t * ) qe ;
2017-03-22 08:56:03 +00:00
isphdr_t * hp ;
2020-11-26 18:47:23 +00:00
uint8_t * resp , * snsp , etype ;
uint16_t scsi_status ;
uint32_t iptr , cont = 0 , cptr , optr , rlen , slen , sptr , totslen ;
1998-09-15 08:42:56 +00:00
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
/*
* We can ' t be getting this now .
*/
if ( isp - > isp_state ! = ISP_RUNSTATE ) {
2017-03-15 14:58:29 +00:00
isp_prt ( isp , ISP_LOGINFO , " respq interrupt when not ready " ) ;
return ;
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
}
2020-11-20 01:15:48 +00:00
iptr = ISP_READ ( isp , BIU2400_RSPINP ) ;
2017-03-15 14:58:29 +00:00
optr = isp - > isp_resodx ;
1998-04-22 17:54:58 +00:00
while ( optr ! = iptr ) {
2017-03-22 08:56:03 +00:00
sptr = cptr = optr ;
hp = ( isphdr_t * ) ISP_QUEUE_ENTRY ( isp - > isp_result , cptr ) ;
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
optr = ISP_NXT_QENTRY ( optr , RESULT_QUEUE_LEN ( isp ) ) ;
2006-11-02 03:21:32 +00:00
1999-10-17 18:58:22 +00:00
/*
Major restructuring for swizzling to the request queue and unswizzling from
the response queue. Instead of the ad hoc ISP_SWIZZLE_REQUEST, we now have
a complete set of inline functions in isp_inline.h. Each platform is
responsible for providing just one of a set of ISP_IOX_{GET,PUT}{8,16,32}
macros.
The reason this needs to be done is that we need to have a single set of
functions that will work correctly on multiple architectures for both little
and big endian machines. It also needs to work correctly in the case that
we have the request or response queues in memory that has to be treated
specially (e.g., have ddi_dma_sync called on it for Solaris after we update
it or before we read from it). It also has to handle the SBus cards (for
platforms that have them) which, while on a Big Endian machine, do *not*
require *most* of the request/response queue entry fields to be swizzled
or unswizzled.
One thing that falls out of this is that we no longer build requests in the
request queue itself. Instead, we build the request locally (e.g., on the
stack) and then as part of the swizzling operation, copy it to the request
queue entry we've allocated. I thought long and hard about whether this was
too expensive a change to make as it in a lot of cases requires an extra
copy. On balance, the flexbility is worth it. With any luck, the entry that
we build locally stays in a processor writeback cache (after all, it's only
64 bytes) so that the cost of actually flushing it to the memory area that is
the shared queue with the PCI device is not all that expensive. We may examine
this again and try to get clever in the future to try and avoid copies.
Another change that falls out of this is that MEMORYBARRIER should be taken
a lot more seriously. The macro ISP_ADD_REQUEST does a MEMORYBARRIER on the
entry being added. But there had been many other places this had been missing.
It's now very important that it be done.
Additional changes:
Fix a longstanding buglet of sorts. When we get an entry via isp_getrqentry,
the iptr value that gets returned is the value we intend to eventually plug
into the ISP registers as the entry *one past* the last one we've written-
*not* the current entry we're updating. All along we've been calling sync
functions on the wrong index value. Argh. The 'fix' here is to rename all
'iptr' variables as 'nxti' to remember that this is the 'next' pointer-
not the current pointer.
Devote a single bit to mboxbsy- and set aside bits for output mbox registers
that we need to pick up- we can have at least one command which does not
have any defined output registers (MBOX_EXECUTE_FIRMWARE).
MFC after: 2 weeks
2001-12-11 00:18:45 +00:00
* Synchronize our view of this response queue entry .
1999-10-17 18:58:22 +00:00
*/
2017-03-22 08:56:03 +00:00
MEMORYBARRIER ( isp , SYNC_RESULT , cptr , QENTRY_LEN , - 1 ) ;
2016-04-11 10:48:26 +00:00
if ( isp - > isp_dblev & ISP_LOGDEBUG1 )
2017-03-22 08:56:03 +00:00
isp_print_qentry ( isp , " Response Queue Entry " , cptr , hp ) ;
2006-11-02 03:21:32 +00:00
isp_get_hdr ( isp , hp , & sp - > req_header ) ;
2020-11-26 18:47:23 +00:00
/*
* Log IOCBs rejected by the firmware . We can ' t really do
* much more about them , since it just should not happen .
*/
if ( sp - > req_header . rqs_flags & RQSFLAG_BADTYPE ) {
isp_print_qentry ( isp , " invalid entry type " , cptr , hp ) ;
continue ;
}
if ( sp - > req_header . rqs_flags & RQSFLAG_BADPARAM ) {
isp_print_qentry ( isp , " invalid entry parameter " , cptr , hp ) ;
continue ;
}
if ( sp - > req_header . rqs_flags & RQSFLAG_BADCOUNT ) {
isp_print_qentry ( isp , " invalid entry count " , cptr , hp ) ;
continue ;
}
if ( sp - > req_header . rqs_flags & RQSFLAG_BADORDER ) {
isp_print_qentry ( isp , " invalid entry order " , cptr , hp ) ;
continue ;
}
2006-11-02 03:21:32 +00:00
etype = sp - > req_header . rqs_entry_type ;
2017-03-22 08:56:03 +00:00
/* We expected Status Continuation, but got different IOCB. */
if ( cont > 0 & & etype ! = RQSTYPE_STATUS_CONT ) {
cont = 0 ;
isp_done ( cont_xs ) ;
}
2020-11-27 15:50:20 +00:00
if ( isp_handle_control ( isp , hp ) ) {
ISP_MEMZERO ( hp , QENTRY_LEN ) ; /* PERF */
continue ;
}
switch ( etype ) {
case RQSTYPE_RESPONSE :
2020-11-20 01:15:48 +00:00
isp_get_24xx_response ( isp , ( isp24xx_statusreq_t * ) hp , sp ) ;
2020-11-27 15:50:20 +00:00
break ;
case RQSTYPE_MARKER :
isp_prt ( isp , ISP_LOG_WARN1 , " Marker Response " ) ;
ISP_MEMZERO ( hp , QENTRY_LEN ) ; /* PERF */
continue ;
case RQSTYPE_STATUS_CONT :
2017-03-22 08:56:03 +00:00
isp_get_cont_response ( isp , ( ispstatus_cont_t * ) hp , scp ) ;
if ( cont > 0 ) {
2020-11-26 18:47:23 +00:00
slen = min ( cont , sizeof ( scp - > req_sense_data ) ) ;
XS_SENSE_APPEND ( cont_xs , scp - > req_sense_data , slen ) ;
cont - = slen ;
2017-03-22 08:56:03 +00:00
if ( cont = = 0 ) {
isp_done ( cont_xs ) ;
} else {
isp_prt ( isp , ISP_LOGDEBUG0 | ISP_LOG_CWARN ,
" Expecting Status Continuations for %u bytes " ,
cont ) ;
}
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
} else {
isp_prt ( isp , ISP_LOG_WARN1 , " Ignored Continuation Response " ) ;
}
2010-02-27 05:41:23 +00:00
ISP_MEMZERO ( hp , QENTRY_LEN ) ; /* PERF */
continue ;
2020-11-27 15:50:20 +00:00
# ifdef ISP_TARGET_MODE
case RQSTYPE_NOTIFY_ACK : /* Can be set to ATIO queue. */
case RQSTYPE_CTIO7 :
case RQSTYPE_ABTS_RCVD : /* Can be set to ATIO queue. */
case RQSTYPE_ABTS_RSP :
isp_target_notify ( isp , hp , & cptr , RESULT_QUEUE_LEN ( isp ) ) ;
2017-03-22 08:56:03 +00:00
/* More then one IOCB could be consumed. */
while ( sptr ! = cptr ) {
2009-08-01 01:04:26 +00:00
ISP_MEMZERO ( hp , QENTRY_LEN ) ; /* PERF */
2017-03-22 08:56:03 +00:00
sptr = ISP_NXT_QENTRY ( sptr , RESULT_QUEUE_LEN ( isp ) ) ;
hp = ( isphdr_t * ) ISP_QUEUE_ENTRY ( isp - > isp_result , sptr ) ;
1998-09-15 08:42:56 +00:00
}
2017-03-22 08:56:03 +00:00
ISP_MEMZERO ( hp , QENTRY_LEN ) ; /* PERF */
optr = ISP_NXT_QENTRY ( cptr , RESULT_QUEUE_LEN ( isp ) ) ;
continue ;
2020-11-27 15:50:20 +00:00
# endif
case RQSTYPE_RPT_ID_ACQ : /* Can be set to ATIO queue.*/
isp_handle_rpt_id_acq ( isp , hp ) ;
ISP_MEMZERO ( hp , QENTRY_LEN ) ; /* PERF */
continue ;
default :
2017-03-22 08:56:03 +00:00
/* We don't know what was this -- log and skip. */
isp_prt ( isp , ISP_LOGERR , notresp , etype , cptr , optr ) ;
ISP_MEMZERO ( hp , QENTRY_LEN ) ; /* PERF */
continue ;
1998-04-22 17:54:58 +00:00
}
1999-10-17 18:58:22 +00:00
xs = isp_find_xs ( isp , sp - > req_handle ) ;
1998-04-22 17:54:58 +00:00
if ( xs = = NULL ) {
2002-04-16 19:55:35 +00:00
/*
* Only whine if this isn ' t the expected fallout of
2009-08-01 01:04:26 +00:00
* aborting the command or resetting the target .
2002-04-16 19:55:35 +00:00
*/
2020-11-26 18:47:23 +00:00
if ( sp - > req_completion_status ! = RQCS_ABORTED & &
sp - > req_completion_status ! = RQCS_RESET_OCCURRED )
isp_prt ( isp , ISP_LOGERR , " cannot find handle 0x%x (status 0x%x) " ,
sp - > req_handle , sp - > req_completion_status ) ;
2009-08-01 01:04:26 +00:00
ISP_MEMZERO ( hp , QENTRY_LEN ) ; /* PERF */
1998-04-22 17:54:58 +00:00
continue ;
}
2000-08-27 23:38:44 +00:00
2020-11-26 18:47:23 +00:00
resp = snsp = sp - > req_rsp_sense ;
2017-03-22 08:56:03 +00:00
rlen = slen = totslen = 0 ;
2020-11-26 18:47:23 +00:00
scsi_status = sp - > req_scsi_status ;
if ( scsi_status & RQCS_RV ) {
2006-11-14 08:45:48 +00:00
rlen = sp - > req_response_len ;
2020-11-26 18:47:23 +00:00
snsp + = rlen ;
2006-11-14 08:45:48 +00:00
}
2020-11-26 18:47:23 +00:00
if ( scsi_status & RQCS_SV ) {
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
totslen = sp - > req_sense_len ;
2020-11-26 18:47:23 +00:00
slen = MIN ( totslen , sizeof ( sp - > req_rsp_sense ) - rlen ) ;
2000-08-27 23:38:44 +00:00
}
2020-11-26 18:47:23 +00:00
* XS_STSP ( xs ) = scsi_status & 0xff ;
if ( scsi_status & RQCS_RESID )
XS_SET_RESID ( xs , sp - > req_fcp_residual ) ;
else
XS_SET_RESID ( xs , 0 ) ;
1998-04-22 17:54:58 +00:00
2017-03-22 08:56:03 +00:00
if ( rlen > = 4 & & resp [ FCP_RSPNS_CODE_OFFSET ] ! = 0 ) {
const char * ptr ;
char lb [ 64 ] ;
const char * rnames [ 10 ] = {
" Task Management function complete " ,
" FCP_DATA length different than FCP_BURST_LEN " ,
" FCP_CMND fields invalid " ,
" FCP_DATA parameter mismatch with FCP_DATA_RO " ,
" Task Management function rejected " ,
" Task Management function failed " ,
NULL ,
NULL ,
" Task Management function succeeded " ,
" Task Management function incorrect logical unit number " ,
} ;
uint8_t code = resp [ FCP_RSPNS_CODE_OFFSET ] ;
2020-11-26 18:47:23 +00:00
if ( code > = nitems ( rnames ) | | rnames [ code ] = = NULL ) {
2017-03-22 08:56:03 +00:00
ISP_SNPRINTF ( lb , sizeof ( lb ) ,
" Unknown FCP Response Code 0x%x " , code ) ;
ptr = lb ;
2006-11-02 03:21:32 +00:00
} else {
2017-03-22 08:56:03 +00:00
ptr = rnames [ code ] ;
2006-11-02 03:21:32 +00:00
}
2017-03-22 08:56:03 +00:00
isp_xs_prt ( isp , xs , ISP_LOGWARN ,
" FCP RESPONSE, LENGTH %u: %s CDB0=0x%02x " ,
rlen , ptr , XS_CDBP ( xs ) [ 0 ] & 0xff ) ;
2020-11-26 18:47:23 +00:00
if ( code ! = FCP_RSPNS_TMF_DONE & &
code ! = FCP_RSPNS_TMF_SUCCEEDED )
2017-03-22 08:56:03 +00:00
XS_SETERR ( xs , HBA_BOTCH ) ;
}
2020-11-26 18:47:23 +00:00
isp_parse_status_24xx ( isp , sp , xs ) ;
2017-03-22 08:56:03 +00:00
if ( slen > 0 ) {
XS_SAVE_SENSE ( xs , snsp , slen ) ;
if ( totslen > slen ) {
cont = totslen - slen ;
cont_xs = xs ;
isp_prt ( isp , ISP_LOGDEBUG0 | ISP_LOG_CWARN ,
" Expecting Status Continuations for %u bytes " ,
cont ) ;
1999-01-10 02:55:10 +00:00
}
1998-04-22 17:54:58 +00:00
}
2000-08-27 23:38:44 +00:00
2020-11-20 18:02:04 +00:00
ISP_DMAFREE ( isp , xs ) ;
2010-01-15 20:08:08 +00:00
isp_destroy_handle ( isp , sp - > req_handle ) ;
2009-08-01 01:04:26 +00:00
ISP_MEMZERO ( hp , QENTRY_LEN ) ; /* PERF */
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
2017-03-22 08:56:03 +00:00
/* Complete command if we expect no Status Continuations. */
if ( cont = = 0 )
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
isp_done ( xs ) ;
1998-09-15 08:42:56 +00:00
}
1998-04-22 17:54:58 +00:00
2017-03-22 08:56:03 +00:00
/* We haven't received all Status Continuations, but that is it. */
if ( cont > 0 )
isp_done ( cont_xs ) ;
2010-03-26 15:13:31 +00:00
2017-03-22 08:56:03 +00:00
/* If we processed any IOCBs, let ISP know about it. */
if ( optr ! = isp - > isp_resodx ) {
2020-11-20 01:15:48 +00:00
ISP_WRITE ( isp , BIU2400_RSPOUTP , optr ) ;
2017-03-22 08:56:03 +00:00
isp - > isp_resodx = optr ;
2010-03-26 15:13:31 +00:00
}
}
2010-02-27 05:41:23 +00:00
2020-11-20 01:15:48 +00:00
void
isp_intr_async ( ispsoftc_t * isp , uint16_t mbox )
2010-02-27 05:41:23 +00:00
{
2015-11-19 17:43:47 +00:00
fcparam * fcp ;
2010-02-27 05:41:23 +00:00
uint16_t chan ;
isp_prt ( isp , ISP_LOGDEBUG2 , " Async Mbox 0x%x " , mbox ) ;
switch ( mbox ) {
case ASYNC_SYSTEM_ERROR :
isp - > isp_state = ISP_CRASHED ;
2020-11-20 01:15:48 +00:00
for ( chan = 0 ; chan < isp - > isp_nchan ; chan + + ) {
FCPARAM ( isp , chan ) - > isp_loopstate = LOOP_NIL ;
isp_change_fw_state ( isp , chan , FW_CONFIG_WAIT ) ;
}
2010-02-27 05:41:23 +00:00
/*
* Were we waiting for a mailbox command to complete ?
* If so , it ' s dead , so wake up the waiter .
*/
if ( isp - > isp_mboxbsy ) {
isp - > isp_obits = 1 ;
isp - > isp_mboxtmp [ 0 ] = MBOX_HOST_INTERFACE_ERROR ;
2020-11-24 15:32:25 +00:00
isp - > isp_mboxbsy = 0 ;
2010-02-27 05:41:23 +00:00
}
/*
* It ' s up to the handler for isp_async to reinit stuff and
* restart the firmware
2020-11-20 01:15:48 +00:00
*/
isp_async ( isp , ISPASYNC_FW_CRASH ) ;
2002-01-03 20:43:22 +00:00
break ;
2020-11-20 01:15:48 +00:00
case ASYNC_RQS_XFER_ERR :
isp_prt ( isp , ISP_LOGERR , " Request Queue Transfer Error " ) ;
2002-01-03 20:43:22 +00:00
break ;
2020-11-20 01:15:48 +00:00
case ASYNC_RSP_XFER_ERR :
isp_prt ( isp , ISP_LOGERR , " Response Queue Transfer Error " ) ;
2010-02-27 05:41:23 +00:00
break ;
1998-09-15 08:42:56 +00:00
2020-11-20 01:15:48 +00:00
case ASYNC_ATIO_XFER_ERR :
isp_prt ( isp , ISP_LOGERR , " ATIO Queue Transfer Error " ) ;
2002-06-16 05:18:22 +00:00
break ;
2020-11-20 01:15:48 +00:00
1998-09-15 08:42:56 +00:00
case ASYNC_LIP_OCCURRED :
2020-11-20 01:15:48 +00:00
case ASYNC_LIP_NOS_OLS_RECV :
case ASYNC_LIP_ERROR :
2009-08-01 01:04:26 +00:00
case ASYNC_PTPMODE :
2001-06-14 17:13:24 +00:00
/*
2009-08-01 01:04:26 +00:00
* These are broadcast events that have to be sent across
* all active channels .
2001-06-14 17:13:24 +00:00
*/
2009-08-01 01:04:26 +00:00
for ( chan = 0 ; chan < isp - > isp_nchan ; chan + + ) {
2015-11-19 17:43:47 +00:00
fcp = FCPARAM ( isp , chan ) ;
2009-08-01 01:04:26 +00:00
int topo = fcp - > isp_topo ;
2015-11-26 13:04:58 +00:00
if ( fcp - > role = = ISP_ROLE_NONE )
2009-08-01 01:04:26 +00:00
continue ;
2015-11-26 13:04:58 +00:00
if ( fcp - > isp_loopstate > LOOP_HAVE_LINK )
fcp - > isp_loopstate = LOOP_HAVE_LINK ;
2009-08-01 01:04:26 +00:00
ISP_SET_SENDMARKER ( isp , chan , 1 ) ;
isp_async ( isp , ISPASYNC_LIP , chan ) ;
# ifdef ISP_TARGET_MODE
2017-03-14 18:42:33 +00:00
isp_target_async ( isp , chan , mbox ) ;
2009-08-01 01:04:26 +00:00
# endif
/*
2016-05-03 03:41:25 +00:00
* We ' ve had problems with data corruption occurring on
2009-08-01 01:04:26 +00:00
* commands that complete ( with no apparent error ) after
* we receive a LIP . This has been observed mostly on
* Local Loop topologies . To be safe , let ' s just mark
2010-02-03 21:09:32 +00:00
* all active initiator commands as dead .
2009-08-01 01:04:26 +00:00
*/
if ( topo = = TOPO_NL_PORT | | topo = = TOPO_FL_PORT ) {
int i , j ;
2020-11-22 04:29:55 +00:00
for ( i = j = 0 ; i < ISP_HANDLE_NUM ( isp ) ; i + + ) {
2009-08-01 01:04:26 +00:00
XS_T * xs ;
2010-02-03 21:09:32 +00:00
isp_hdl_t * hdp ;
hdp = & isp - > isp_xflist [ i ] ;
if ( ISP_H2HT ( hdp - > handle ) ! = ISP_HANDLE_INITIATOR ) {
2009-08-01 01:04:26 +00:00
continue ;
}
2010-02-03 21:09:32 +00:00
xs = hdp - > cmd ;
2009-08-01 01:04:26 +00:00
if ( XS_CHANNEL ( xs ) ! = chan ) {
continue ;
}
2001-06-14 17:13:24 +00:00
j + + ;
2015-10-24 17:34:40 +00:00
isp_prt ( isp , ISP_LOG_WARN1 ,
" %d.%d.%jx bus reset set at %s:%u " ,
XS_CHANNEL ( xs ) , XS_TGT ( xs ) ,
( uintmax_t ) XS_LUN ( xs ) ,
__func__ , __LINE__ ) ;
2001-06-14 17:13:24 +00:00
XS_SETERR ( xs , HBA_BUSRESET ) ;
}
2009-08-01 01:04:26 +00:00
if ( j ) {
isp_prt ( isp , ISP_LOGERR , lipd , chan , j ) ;
}
2001-07-04 18:42:41 +00:00
}
2001-06-14 17:13:24 +00:00
}
1998-09-15 08:42:56 +00:00
break ;
case ASYNC_LOOP_UP :
2009-08-01 01:04:26 +00:00
/*
* This is a broadcast event that has to be sent across
* all active channels .
*/
for ( chan = 0 ; chan < isp - > isp_nchan ; chan + + ) {
2015-11-19 17:43:47 +00:00
fcp = FCPARAM ( isp , chan ) ;
if ( fcp - > role = = ISP_ROLE_NONE )
2009-08-01 01:04:26 +00:00
continue ;
2015-11-26 13:04:58 +00:00
fcp - > isp_linkstate = 1 ;
if ( fcp - > isp_loopstate < LOOP_HAVE_LINK )
fcp - > isp_loopstate = LOOP_HAVE_LINK ;
2009-08-01 01:04:26 +00:00
ISP_SET_SENDMARKER ( isp , chan , 1 ) ;
isp_async ( isp , ISPASYNC_LOOP_UP , chan ) ;
# ifdef ISP_TARGET_MODE
2017-03-14 18:42:33 +00:00
isp_target_async ( isp , chan , mbox ) ;
2000-01-03 23:52:41 +00:00
# endif
2009-08-01 01:04:26 +00:00
}
1998-09-15 08:42:56 +00:00
break ;
case ASYNC_LOOP_DOWN :
2009-08-01 01:04:26 +00:00
/*
* This is a broadcast event that has to be sent across
* all active channels .
*/
for ( chan = 0 ; chan < isp - > isp_nchan ; chan + + ) {
2015-11-19 17:43:47 +00:00
fcp = FCPARAM ( isp , chan ) ;
if ( fcp - > role = = ISP_ROLE_NONE )
2009-08-01 01:04:26 +00:00
continue ;
ISP_SET_SENDMARKER ( isp , chan , 1 ) ;
2015-11-26 13:04:58 +00:00
fcp - > isp_linkstate = 0 ;
2009-08-01 01:04:26 +00:00
fcp - > isp_loopstate = LOOP_NIL ;
isp_async ( isp , ISPASYNC_LOOP_DOWN , chan ) ;
# ifdef ISP_TARGET_MODE
2017-03-14 18:42:33 +00:00
isp_target_async ( isp , chan , mbox ) ;
2000-01-03 23:52:41 +00:00
# endif
2009-08-01 01:04:26 +00:00
}
1998-09-15 08:42:56 +00:00
break ;
case ASYNC_LOOP_RESET :
2009-08-01 01:04:26 +00:00
/*
* This is a broadcast event that has to be sent across
* all active channels .
*/
for ( chan = 0 ; chan < isp - > isp_nchan ; chan + + ) {
2015-11-19 17:43:47 +00:00
fcp = FCPARAM ( isp , chan ) ;
if ( fcp - > role = = ISP_ROLE_NONE )
2009-08-01 01:04:26 +00:00
continue ;
ISP_SET_SENDMARKER ( isp , chan , 1 ) ;
2015-11-26 13:04:58 +00:00
if ( fcp - > isp_loopstate > LOOP_HAVE_LINK )
fcp - > isp_loopstate = LOOP_HAVE_LINK ;
2009-08-01 01:04:26 +00:00
isp_async ( isp , ISPASYNC_LOOP_RESET , chan ) ;
# ifdef ISP_TARGET_MODE
2017-03-14 18:42:33 +00:00
isp_target_async ( isp , chan , mbox ) ;
1998-12-05 01:33:57 +00:00
# endif
2009-08-01 01:04:26 +00:00
}
1998-09-15 08:42:56 +00:00
break ;
case ASYNC_PDB_CHANGED :
2009-08-01 01:04:26 +00:00
{
2015-10-25 14:34:07 +00:00
int echan , nphdl , nlstate , reason ;
2020-11-20 01:15:48 +00:00
nphdl = ISP_READ ( isp , OUTMAILBOX1 ) ;
nlstate = ISP_READ ( isp , OUTMAILBOX2 ) ;
reason = ISP_READ ( isp , OUTMAILBOX3 ) > > 8 ;
2015-11-19 17:43:47 +00:00
if ( ISP_CAP_MULTI_ID ( isp ) ) {
chan = ISP_READ ( isp , OUTMAILBOX3 ) & 0xff ;
if ( chan = = 0xff | | nphdl = = NIL_HANDLE ) {
chan = 0 ;
echan = isp - > isp_nchan - 1 ;
} else if ( chan > = isp - > isp_nchan ) {
break ;
} else {
echan = chan ;
}
2009-08-01 01:04:26 +00:00
} else {
2015-10-25 14:34:07 +00:00
chan = echan = 0 ;
2009-08-01 01:04:26 +00:00
}
2015-10-25 14:34:07 +00:00
for ( ; chan < = echan ; chan + + ) {
2015-11-19 17:43:47 +00:00
fcp = FCPARAM ( isp , chan ) ;
if ( fcp - > role = = ISP_ROLE_NONE )
2009-08-01 01:04:26 +00:00
continue ;
2016-04-13 10:35:17 +00:00
if ( fcp - > isp_loopstate > LOOP_LTEST_DONE ) {
if ( nphdl ! = NIL_HANDLE & &
nphdl = = fcp - > isp_login_hdl & &
reason = = PDB24XX_AE_OPN_2 )
continue ;
2015-11-17 16:33:46 +00:00
fcp - > isp_loopstate = LOOP_LTEST_DONE ;
2016-04-13 10:35:17 +00:00
} else if ( fcp - > isp_loopstate < LOOP_HAVE_LINK )
2015-11-26 13:04:58 +00:00
fcp - > isp_loopstate = LOOP_HAVE_LINK ;
2015-11-19 17:43:47 +00:00
isp_async ( isp , ISPASYNC_CHANGE_NOTIFY , chan ,
ISPASYNC_CHANGE_PDB , nphdl , nlstate , reason ) ;
2009-08-01 01:04:26 +00:00
}
break ;
}
1998-09-15 08:42:56 +00:00
case ASYNC_CHANGE_NOTIFY :
2009-08-01 01:04:26 +00:00
{
2015-11-19 17:43:47 +00:00
int portid ;
2009-08-01 01:04:26 +00:00
2015-11-19 17:43:47 +00:00
portid = ( ( ISP_READ ( isp , OUTMAILBOX1 ) & 0xff ) < < 16 ) |
ISP_READ ( isp , OUTMAILBOX2 ) ;
if ( ISP_CAP_MULTI_ID ( isp ) ) {
chan = ISP_READ ( isp , OUTMAILBOX3 ) & 0xff ;
if ( chan > = isp - > isp_nchan )
break ;
2006-11-02 03:21:32 +00:00
} else {
2015-11-19 17:43:47 +00:00
chan = 0 ;
2006-11-02 03:21:32 +00:00
}
2015-11-19 17:43:47 +00:00
fcp = FCPARAM ( isp , chan ) ;
if ( fcp - > role = = ISP_ROLE_NONE )
break ;
2015-11-22 17:03:38 +00:00
if ( fcp - > isp_loopstate > LOOP_LTEST_DONE )
fcp - > isp_loopstate = LOOP_LTEST_DONE ;
2015-11-26 13:04:58 +00:00
else if ( fcp - > isp_loopstate < LOOP_HAVE_LINK )
fcp - > isp_loopstate = LOOP_HAVE_LINK ;
2015-11-19 17:43:47 +00:00
isp_async ( isp , ISPASYNC_CHANGE_NOTIFY , chan ,
ISPASYNC_CHANGE_SNS , portid ) ;
2000-02-11 19:31:32 +00:00
break ;
2009-08-01 01:04:26 +00:00
}
2015-11-22 11:44:30 +00:00
case ASYNC_ERR_LOGGING_DISABLED :
isp_prt ( isp , ISP_LOGWARN , " Error logging disabled (reason 0x%x) " ,
ISP_READ ( isp , OUTMAILBOX1 ) ) ;
break ;
case ASYNC_P2P_INIT_ERR :
2020-11-20 01:15:48 +00:00
isp_prt ( isp , ISP_LOGWARN , " P2P init error (reason 0x%x) " ,
ISP_READ ( isp , OUTMAILBOX1 ) ) ;
1998-09-15 08:42:56 +00:00
break ;
2020-11-20 01:15:48 +00:00
case ASYNC_RCV_ERR :
isp_prt ( isp , ISP_LOGWARN , " Receive Error " ) ;
1998-09-15 08:42:56 +00:00
break ;
2020-11-20 01:15:48 +00:00
case ASYNC_RJT_SENT : /* same as ASYNC_QFULL_SENT */
isp_prt ( isp , ISP_LOGTDEBUG0 , " LS_RJT sent " ) ;
1998-09-15 08:42:56 +00:00
break ;
2020-11-20 01:15:48 +00:00
case ASYNC_FW_RESTART_COMPLETE :
isp_prt ( isp , ISP_LOGDEBUG0 , " FW restart complete " ) ;
1998-09-15 08:42:56 +00:00
break ;
2020-11-20 01:15:48 +00:00
case ASYNC_TEMPERATURE_ALERT :
isp_prt ( isp , ISP_LOGERR , " Temperature alert (subcode 0x%x) " ,
ISP_READ ( isp , OUTMAILBOX1 ) ) ;
2006-11-02 03:21:32 +00:00
break ;
2020-11-26 02:14:52 +00:00
case ASYNC_INTER_DRIVER_COMP :
isp_prt ( isp , ISP_LOGDEBUG0 , " Inter-driver communication complete " ) ;
break ;
case ASYNC_INTER_DRIVER_NOTIFY :
isp_prt ( isp , ISP_LOGDEBUG0 , " Inter-driver communication notification " ) ;
break ;
case ASYNC_INTER_DRIVER_TIME_EXT :
isp_prt ( isp , ISP_LOGDEBUG0 , " Inter-driver communication time extended " ) ;
break ;
2020-11-20 01:15:48 +00:00
case ASYNC_TRANSCEIVER_INSERTION :
isp_prt ( isp , ISP_LOGDEBUG0 , " Transceiver insertion (0x%x) " ,
ISP_READ ( isp , OUTMAILBOX1 ) ) ;
2006-11-02 03:21:32 +00:00
break ;
2020-11-20 01:15:48 +00:00
case ASYNC_TRANSCEIVER_REMOVAL :
isp_prt ( isp , ISP_LOGDEBUG0 , " Transceiver removal " ) ;
2006-11-02 03:21:32 +00:00
break ;
2020-11-26 02:14:52 +00:00
case ASYNC_NIC_FW_STATE_CHANGE :
isp_prt ( isp , ISP_LOGDEBUG0 , " NIC Firmware State Change " ) ;
break ;
2020-11-20 01:15:48 +00:00
case ASYNC_AUTOLOAD_FW_COMPLETE :
isp_prt ( isp , ISP_LOGDEBUG0 , " Autoload FW init complete " ) ;
break ;
case ASYNC_AUTOLOAD_FW_FAILURE :
isp_prt ( isp , ISP_LOGERR , " Autoload FW init failure " ) ;
break ;
default :
isp_prt ( isp , ISP_LOGWARN , " Unknown Async Code 0x%x " , mbox ) ;
break ;
}
}
2006-11-02 03:21:32 +00:00
2020-11-20 01:15:48 +00:00
/*
2020-11-27 15:50:20 +00:00
* Handle completions with control handles by waking up waiting threads .
2020-11-20 01:15:48 +00:00
*/
static int
2020-11-27 15:50:20 +00:00
isp_handle_control ( ispsoftc_t * isp , isphdr_t * hp )
2020-11-20 01:15:48 +00:00
{
2020-11-27 15:50:20 +00:00
uint32_t hdl ;
2020-11-20 01:15:48 +00:00
void * ptr ;
2017-03-14 08:45:33 +00:00
2020-11-27 15:50:20 +00:00
switch ( hp - > rqs_entry_type ) {
case RQSTYPE_RESPONSE :
2020-11-20 01:15:48 +00:00
case RQSTYPE_MARKER :
2020-11-27 15:50:20 +00:00
case RQSTYPE_NOTIFY_ACK :
case RQSTYPE_CTIO7 :
case RQSTYPE_TSK_MGMT :
2020-11-20 01:15:48 +00:00
case RQSTYPE_CT_PASSTHRU :
case RQSTYPE_VP_MODIFY :
case RQSTYPE_VP_CTRL :
2020-11-27 15:50:20 +00:00
case RQSTYPE_ABORT_IO :
case RQSTYPE_MBOX :
2020-11-20 01:15:48 +00:00
case RQSTYPE_LOGIN :
2020-11-27 15:50:20 +00:00
case RQSTYPE_ELS_PASSTHRU :
2020-11-20 01:15:48 +00:00
ISP_IOXGET_32 ( isp , ( uint32_t * ) ( hp + 1 ) , hdl ) ;
2020-11-27 15:50:20 +00:00
if ( ISP_H2HT ( hdl ) ! = ISP_HANDLE_CTRL )
break ;
2020-11-20 01:15:48 +00:00
ptr = isp_find_xs ( isp , hdl ) ;
if ( ptr ! = NULL ) {
isp_destroy_handle ( isp , hdl ) ;
memcpy ( ptr , hp , QENTRY_LEN ) ;
wakeup ( ptr ) ;
2006-11-02 03:21:32 +00:00
}
2020-11-20 01:15:48 +00:00
return ( 1 ) ;
2020-11-27 15:50:20 +00:00
}
return ( 0 ) ;
}
static void
isp_handle_rpt_id_acq ( ispsoftc_t * isp , isphdr_t * hp )
{
fcparam * fcp ;
isp_ridacq_t rid ;
int chan , c ;
uint32_t portid ;
isp_get_ridacq ( isp , ( isp_ridacq_t * ) hp , & rid ) ;
portid = ( uint32_t ) rid . ridacq_vp_port_hi < < 16 |
rid . ridacq_vp_port_lo ;
if ( rid . ridacq_format = = 0 ) {
for ( chan = 0 ; chan < isp - > isp_nchan ; chan + + ) {
fcp = FCPARAM ( isp , chan ) ;
if ( fcp - > role = = ISP_ROLE_NONE )
continue ;
c = ( chan = = 0 ) ? 127 : ( chan - 1 ) ;
if ( rid . ridacq_map [ c / 16 ] & ( 1 < < ( c % 16 ) ) | |
chan = = 0 ) {
fcp - > isp_loopstate = LOOP_HAVE_LINK ;
isp_async ( isp , ISPASYNC_CHANGE_NOTIFY ,
chan , ISPASYNC_CHANGE_OTHER ) ;
} else {
fcp - > isp_loopstate = LOOP_NIL ;
isp_async ( isp , ISPASYNC_LOOP_DOWN ,
chan ) ;
}
}
} else {
fcp = FCPARAM ( isp , rid . ridacq_vp_index ) ;
if ( rid . ridacq_vp_status = = RIDACQ_STS_COMPLETE | |
rid . ridacq_vp_status = = RIDACQ_STS_CHANGED ) {
fcp - > isp_topo = ( rid . ridacq_map [ 0 ] > > 9 ) & 0x7 ;
fcp - > isp_portid = portid ;
fcp - > isp_loopstate = LOOP_HAVE_ADDR ;
isp_async ( isp , ISPASYNC_CHANGE_NOTIFY ,
rid . ridacq_vp_index , ISPASYNC_CHANGE_OTHER ) ;
} else {
fcp - > isp_loopstate = LOOP_NIL ;
isp_async ( isp , ISPASYNC_LOOP_DOWN ,
rid . ridacq_vp_index ) ;
}
2006-11-02 03:21:32 +00:00
}
}
static void
2020-11-26 18:47:23 +00:00
isp_parse_status_24xx ( ispsoftc_t * isp , isp24xx_statusreq_t * sp , XS_T * xs )
2006-11-02 03:21:32 +00:00
{
2007-07-02 20:08:20 +00:00
int ru_marked , sv_marked ;
2009-08-01 01:04:26 +00:00
int chan = XS_CHANNEL ( xs ) ;
2006-11-02 03:21:32 +00:00
switch ( sp - > req_completion_status ) {
case RQCS_COMPLETE :
return ;
case RQCS_DMA_ERROR :
2010-03-26 15:13:31 +00:00
isp_xs_prt ( isp , xs , ISP_LOGERR , " DMA error " ) ;
2020-11-26 18:47:23 +00:00
if ( XS_NOERR ( xs ) )
XS_SETERR ( xs , HBA_BOTCH ) ;
2006-11-02 03:21:32 +00:00
break ;
case RQCS_TRANSPORT_ERROR :
2010-03-26 15:13:31 +00:00
isp_xs_prt ( isp , xs , ISP_LOGERR , " Transport Error " ) ;
2020-11-26 18:47:23 +00:00
if ( XS_NOERR ( xs ) )
XS_SETERR ( xs , HBA_BOTCH ) ;
2006-11-02 03:21:32 +00:00
break ;
case RQCS_RESET_OCCURRED :
2010-03-26 15:13:31 +00:00
isp_xs_prt ( isp , xs , ISP_LOGWARN , " reset destroyed command " ) ;
2009-08-01 01:04:26 +00:00
FCPARAM ( isp , chan ) - > sendmarker = 1 ;
2020-11-26 18:47:23 +00:00
if ( XS_NOERR ( xs ) )
2006-11-02 03:21:32 +00:00
XS_SETERR ( xs , HBA_BUSRESET ) ;
return ;
case RQCS_ABORTED :
2010-03-26 15:13:31 +00:00
isp_xs_prt ( isp , xs , ISP_LOGERR , " Command Aborted " ) ;
2009-08-01 01:04:26 +00:00
FCPARAM ( isp , chan ) - > sendmarker = 1 ;
2020-11-26 18:47:23 +00:00
if ( XS_NOERR ( xs ) )
2006-11-02 03:21:32 +00:00
XS_SETERR ( xs , HBA_ABORTED ) ;
return ;
case RQCS_TIMEOUT :
2010-03-26 15:13:31 +00:00
isp_xs_prt ( isp , xs , ISP_LOGWARN , " Command Timed Out " ) ;
2020-11-26 18:47:23 +00:00
if ( XS_NOERR ( xs ) )
2006-11-02 03:21:32 +00:00
XS_SETERR ( xs , HBA_CMDTIMEOUT ) ;
1998-04-22 17:54:58 +00:00
return ;
2006-11-02 03:21:32 +00:00
case RQCS_DATA_OVERRUN :
2009-08-01 01:04:26 +00:00
XS_SET_RESID ( xs , sp - > req_resid ) ;
2010-03-26 15:13:31 +00:00
isp_xs_prt ( isp , xs , ISP_LOGERR , " Data Overrun " ) ;
2020-11-26 18:47:23 +00:00
if ( XS_NOERR ( xs ) )
2006-11-02 03:21:32 +00:00
XS_SETERR ( xs , HBA_DATAOVR ) ;
return ;
2020-11-26 18:47:23 +00:00
case RQCS_DRE : /* data reassembly error */
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
isp_prt ( isp , ISP_LOGERR , " Chan %d data reassembly error for target %d " , chan , XS_TGT ( xs ) ) ;
2020-11-26 18:47:23 +00:00
if ( XS_NOERR ( xs ) )
XS_SETERR ( xs , HBA_BOTCH ) ;
1998-04-22 17:54:58 +00:00
return ;
2020-11-26 18:47:23 +00:00
case RQCS_TABORT : /* aborted by target */
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
isp_prt ( isp , ISP_LOGERR , " Chan %d target %d sent ABTS " , chan , XS_TGT ( xs ) ) ;
2020-11-26 18:47:23 +00:00
if ( XS_NOERR ( xs ) )
2006-11-02 03:21:32 +00:00
XS_SETERR ( xs , HBA_ABORTED ) ;
return ;
1998-09-15 08:42:56 +00:00
2006-11-02 03:21:32 +00:00
case RQCS_DATA_UNDERRUN :
2007-07-02 20:08:20 +00:00
ru_marked = ( sp - > req_scsi_status & RQCS_RU ) ! = 0 ;
/*
2009-08-01 01:04:26 +00:00
* We can get an underrun w / o things being marked
2007-07-02 20:08:20 +00:00
* if we got a non - zero status .
*/
sv_marked = ( sp - > req_scsi_status & ( RQCS_SV | RQCS_RV ) ) ! = 0 ;
if ( ( ru_marked = = 0 & & sv_marked = = 0 ) | |
( sp - > req_resid > XS_XFRLEN ( xs ) ) ) {
2010-03-26 15:13:31 +00:00
isp_xs_prt ( isp , xs , ISP_LOGWARN , bun , XS_XFRLEN ( xs ) , sp - > req_resid , ( ru_marked ) ? " marked " : " not marked " ) ;
2020-11-26 18:47:23 +00:00
if ( XS_NOERR ( xs ) )
2007-07-02 20:08:20 +00:00
XS_SETERR ( xs , HBA_BOTCH ) ;
return ;
}
2009-08-01 01:04:26 +00:00
XS_SET_RESID ( xs , sp - > req_resid ) ;
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
isp_xs_prt ( isp , xs , ISP_LOG_WARN1 , " Data Underrun (%d) for command 0x%x " , sp - > req_resid , XS_CDBP ( xs ) [ 0 ] & 0xff ) ;
2006-11-02 03:21:32 +00:00
return ;
1998-09-15 08:42:56 +00:00
1998-04-22 17:54:58 +00:00
case RQCS_PORT_UNAVAILABLE :
/*
* No such port on the loop . Moral equivalent of SELTIMEO
*/
case RQCS_PORT_LOGGED_OUT :
2006-11-02 03:21:32 +00:00
{
2007-03-22 23:38:32 +00:00
const char * reason ;
2006-11-02 03:21:32 +00:00
uint8_t sts = sp - > req_completion_status & 0xff ;
2016-05-17 15:12:57 +00:00
fcparam * fcp = FCPARAM ( isp , XS_CHANNEL ( xs ) ) ;
fcportdb_t * lp ;
2006-11-02 03:21:32 +00:00
1998-09-15 08:42:56 +00:00
/*
* It was there ( maybe ) - treat as a selection timeout .
*/
2006-11-02 03:21:32 +00:00
if ( sts = = RQCS_PORT_UNAVAILABLE ) {
reason = " unavailable " ;
} else {
reason = " logout " ;
}
2009-08-01 01:04:26 +00:00
isp_prt ( isp , ISP_LOGINFO , " Chan %d port %s for target %d " ,
chan , reason , XS_TGT ( xs ) ) ;
2006-11-02 03:21:32 +00:00
2017-03-14 08:45:33 +00:00
/* XXX: Should we trigger rescan or FW announce change? */
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
if ( XS_NOERR ( xs ) ) {
2016-05-17 15:12:57 +00:00
lp = & fcp - > portdb [ XS_TGT ( xs ) ] ;
if ( lp - > state = = FC_PORTDB_STATE_ZOMBIE ) {
* XS_STSP ( xs ) = SCSI_BUSY ;
XS_SETERR ( xs , HBA_TGTBSY ) ;
} else
XS_SETERR ( xs , HBA_SELTIMEOUT ) ;
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
}
1998-09-15 08:42:56 +00:00
return ;
2006-11-02 03:21:32 +00:00
}
1998-04-22 17:54:58 +00:00
case RQCS_PORT_CHANGED :
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
isp_prt ( isp , ISP_LOGWARN , " port changed for target %d chan %d " , XS_TGT ( xs ) , chan ) ;
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
if ( XS_NOERR ( xs ) ) {
2017-03-12 15:36:07 +00:00
* XS_STSP ( xs ) = SCSI_BUSY ;
XS_SETERR ( xs , HBA_TGTBSY ) ;
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
}
2000-02-29 05:52:14 +00:00
return ;
1998-04-22 17:54:58 +00:00
2020-11-26 18:47:23 +00:00
case RQCS_ENOMEM : /* f/w resource unavailable */
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
isp_prt ( isp , ISP_LOGWARN , " f/w resource unavailable for target %d chan %d " , XS_TGT ( xs ) , chan ) ;
2006-11-02 03:21:32 +00:00
if ( XS_NOERR ( xs ) ) {
2020-11-20 01:15:48 +00:00
* XS_STSP ( xs ) = SCSI_BUSY ;
XS_SETERR ( xs , HBA_TGTBSY ) ;
}
return ;
2020-11-26 18:47:23 +00:00
case RQCS_TMO : /* task management overrun */
2020-11-20 01:15:48 +00:00
isp_prt ( isp , ISP_LOGWARN , " command for target %d overlapped task management for chan %d " , XS_TGT ( xs ) , chan ) ;
if ( XS_NOERR ( xs ) ) {
* XS_STSP ( xs ) = SCSI_BUSY ;
XS_SETERR ( xs , HBA_TGTBSY ) ;
}
return ;
default :
isp_prt ( isp , ISP_LOGERR , " Unknown Completion Status 0x%x on chan %d " , sp - > req_completion_status , chan ) ;
break ;
}
2020-11-26 18:47:23 +00:00
if ( XS_NOERR ( xs ) )
2020-11-20 01:15:48 +00:00
XS_SETERR ( xs , HBA_BOTCH ) ;
}
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
2012-06-17 21:39:40 +00:00
# define ISP_FC_IBITS(op) ((mbpfc[((op)<<3) + 0] << 24) | (mbpfc[((op)<<3) + 1] << 16) | (mbpfc[((op)<<3) + 2] << 8) | (mbpfc[((op)<<3) + 3]))
# define ISP_FC_OBITS(op) ((mbpfc[((op)<<3) + 4] << 24) | (mbpfc[((op)<<3) + 5] << 16) | (mbpfc[((op)<<3) + 6] << 8) | (mbpfc[((op)<<3) + 7]))
# define ISP_FC_OPMAP(in0, out0) 0, 0, 0, in0, 0, 0, 0, out0
# define ISP_FC_OPMAP_HALF(in1, in0, out1, out0) 0, 0, in1, in0, 0, 0, out1, out0
# define ISP_FC_OPMAP_FULL(in3, in2, in1, in0, out3, out2, out1, out0) in3, in2, in1, in0, out3, out2, out1, out0
2006-02-15 00:31:48 +00:00
static const uint32_t mbpfc [ ] = {
2012-06-17 21:39:40 +00:00
ISP_FC_OPMAP ( 0x01 , 0x01 ) , /* 0x00: MBOX_NO_OP */
ISP_FC_OPMAP ( 0x1f , 0x01 ) , /* 0x01: MBOX_LOAD_RAM */
2018-03-15 01:07:21 +00:00
ISP_FC_OPMAP_HALF ( 0x07 , 0xff , 0x00 , 0x1f ) , /* 0x02: MBOX_EXEC_FIRMWARE */
2012-06-17 21:39:40 +00:00
ISP_FC_OPMAP ( 0xdf , 0x01 ) , /* 0x03: MBOX_DUMP_RAM */
ISP_FC_OPMAP ( 0x07 , 0x07 ) , /* 0x04: MBOX_WRITE_RAM_WORD */
ISP_FC_OPMAP ( 0x03 , 0x07 ) , /* 0x05: MBOX_READ_RAM_WORD */
ISP_FC_OPMAP_FULL ( 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ) , /* 0x06: MBOX_MAILBOX_REG_TEST */
ISP_FC_OPMAP ( 0x07 , 0x07 ) , /* 0x07: MBOX_VERIFY_CHECKSUM */
-----------
MISC CHANGES
Add a new async event- ISP_TARGET_NOTIFY_ACK, that will guarantee
eventual delivery of a NOTIFY ACK. This is tons better than just
ignoring the return from isp_notify_ack and hoping for the best.
Clean up the lower level lun enable code to be a bit more sensible.
Fix a botch in isp_endcmd which was messing up the sense data.
Fix notify ack for SRR to use a sensible error code in the case
of a reject.
Clean up and make clear what kind of firmware we've loaded and
what capabilities it has.
-----------
FULL (252 byte) SENSE DATA
In CTIOs for the ISP, there's only a limimted amount of space
to load SENSE DATA for associated CHECK CONDITIONS (24 or 26
bytes). This makes it difficult to send full SENSE DATA that can
be up to 252 bytes.
Implement MODE 2 responses which have us build the FCP Response
in system memory which the ISP will put onto the wire directly.
On the initiator side, the same problem occurs in that a command
status response only has a limited amount of space for SENSE DATA.
This data is supplemented by status continuation responses that
the ISP pushes onto the response queue after the status response.
We now pull them all together so that full sense data can be
returned to the periph driver.
This is supported on 23XX, 24XX and 25XX cards.
This is also preparation for doing >16 byte CDBs.
-----------
FC TAPE
Implement full FC-TAPE on both initiator and target mode side. This
capability is driven by firmware loaded, board type, board NVRAM
settings, or hint configuration options to enable or disable. This
is supported for 23XX, 24XX and 25XX cards.
On the initiator side, we pretty much just have to generate a command
reference number for each command we send out. This is FCP-4 compliant
in that we do this per ITL nexus to generate the allowed 1 thru 255
CRN.
In order to support the target side of FC-TAPE, we now pay attention
to more of the PRLI word 3 parameters which will tell us whether
an initiator wants confirmed responses. While we're at it, we'll
pay attention to the initiator view too and report it.
On sending back CTIOs, we will notice whether the initiator wants
confirmed responses and we'll set up flags to do so.
If a response or data frame is lost the initiator sends us an SRR
(Sequence Retransmit Request) ELS which shows up as an SRR notify
and all outstanding CTIOs are nuked with SRR Received status. The
SRR notify contains the offset that the initiator wants us to restart
the data transfer from or to retransmit the response frame.
If the ISP driver still has the CCB around for which the data segment
or response applies, it will retransmit.
However, we typically don't know about a lost data frame until we
send the FCP Response and the initiator totes up counters for data
moved and notices missing segments. In this case we've already
completed the data CCBs already and sent themn back up to the periph
driver. Because there's no really clean mechanism yet in CAM to
handle this, a hack has been put into place to complete the CTIO
CCB with the CAM_MESSAGE_RECV status which will have a MODIFY DATA
POINTER extended message in it. The internal ISP target groks this
and ctl(8) will be modified to deal with this as well.
At any rate, the data is retransmitted and an an FCP response is
sent. The whole point here is to successfully complete a command
so that you don't have to depend on ULP (SCSI) to have to recover,
which in the case of tape is not really possible (hence the name
FC-TAPE).
Sponsored by: Spectralogic
MFC after: 1 month
2012-07-28 20:06:29 +00:00
ISP_FC_OPMAP_FULL ( 0x0 , 0x0 , 0x0 , 0x01 , 0x0 , 0x3 , 0x80 , 0x7f ) , /* 0x08: MBOX_ABOUT_FIRMWARE */
2012-06-17 21:39:40 +00:00
ISP_FC_OPMAP ( 0xdf , 0x01 ) , /* 0x09: MBOX_LOAD_RISC_RAM_2100 */
ISP_FC_OPMAP ( 0xdf , 0x01 ) , /* 0x0a: DUMP RAM */
ISP_FC_OPMAP_HALF ( 0x1 , 0xff , 0x0 , 0x01 ) , /* 0x0b: MBOX_LOAD_RISC_RAM */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x0c: */
ISP_FC_OPMAP_HALF ( 0x1 , 0x0f , 0x0 , 0x01 ) , /* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED */
ISP_FC_OPMAP ( 0x01 , 0x05 ) , /* 0x0e: MBOX_CHECK_FIRMWARE */
ISP_FC_OPMAP_HALF ( 0x1 , 0x03 , 0x0 , 0x0d ) , /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED */
ISP_FC_OPMAP ( 0x1f , 0x11 ) , /* 0x10: MBOX_INIT_REQ_QUEUE */
ISP_FC_OPMAP ( 0x2f , 0x21 ) , /* 0x11: MBOX_INIT_RES_QUEUE */
ISP_FC_OPMAP ( 0x0f , 0x01 ) , /* 0x12: MBOX_EXECUTE_IOCB */
ISP_FC_OPMAP ( 0x03 , 0x03 ) , /* 0x13: MBOX_WAKE_UP */
2015-11-22 15:57:54 +00:00
ISP_FC_OPMAP_HALF ( 0x1 , 0xff , 0x0 , 0x03 ) , /* 0x14: MBOX_STOP_FIRMWARE */
2012-06-17 21:39:40 +00:00
ISP_FC_OPMAP ( 0x4f , 0x01 ) , /* 0x15: MBOX_ABORT */
ISP_FC_OPMAP ( 0x07 , 0x01 ) , /* 0x16: MBOX_ABORT_DEVICE */
ISP_FC_OPMAP ( 0x07 , 0x01 ) , /* 0x17: MBOX_ABORT_TARGET */
ISP_FC_OPMAP ( 0x03 , 0x03 ) , /* 0x18: MBOX_BUS_RESET */
ISP_FC_OPMAP ( 0x07 , 0x05 ) , /* 0x19: MBOX_STOP_QUEUE */
ISP_FC_OPMAP ( 0x07 , 0x05 ) , /* 0x1a: MBOX_START_QUEUE */
ISP_FC_OPMAP ( 0x07 , 0x05 ) , /* 0x1b: MBOX_SINGLE_STEP_QUEUE */
ISP_FC_OPMAP ( 0x07 , 0x05 ) , /* 0x1c: MBOX_ABORT_QUEUE */
ISP_FC_OPMAP ( 0x07 , 0x03 ) , /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x1e: */
ISP_FC_OPMAP ( 0x01 , 0x07 ) , /* 0x1f: MBOX_GET_FIRMWARE_STATUS */
2015-10-28 12:34:59 +00:00
ISP_FC_OPMAP_HALF ( 0x2 , 0x01 , 0x7e , 0xcf ) , /* 0x20: MBOX_GET_LOOP_ID */
2012-06-17 21:39:40 +00:00
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x21: */
2015-12-24 14:53:29 +00:00
ISP_FC_OPMAP ( 0x03 , 0x4b ) , /* 0x22: MBOX_GET_TIMEOUT_PARAMS */
2012-06-17 21:39:40 +00:00
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x23: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x24: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x25: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x26: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x27: */
ISP_FC_OPMAP ( 0x01 , 0x03 ) , /* 0x28: MBOX_GET_FIRMWARE_OPTIONS */
ISP_FC_OPMAP ( 0x03 , 0x07 ) , /* 0x29: MBOX_GET_PORT_QUEUE_PARAMS */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x2a: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x2b: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x2c: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x2d: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x2e: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x2f: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x30: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x31: */
2015-12-24 14:53:29 +00:00
ISP_FC_OPMAP ( 0x4b , 0x4b ) , /* 0x32: MBOX_SET_TIMEOUT_PARAMS */
2012-06-17 21:39:40 +00:00
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x33: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x34: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x35: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x36: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x37: */
ISP_FC_OPMAP ( 0x0f , 0x01 ) , /* 0x38: MBOX_SET_FIRMWARE_OPTIONS */
ISP_FC_OPMAP ( 0x0f , 0x07 ) , /* 0x39: MBOX_SET_PORT_QUEUE_PARAMS */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x3a: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x3b: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x3c: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x3d: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x3e: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x3f: */
ISP_FC_OPMAP ( 0x03 , 0x01 ) , /* 0x40: MBOX_LOOP_PORT_BYPASS */
ISP_FC_OPMAP ( 0x03 , 0x01 ) , /* 0x41: MBOX_LOOP_PORT_ENABLE */
2017-02-27 08:20:28 +00:00
ISP_FC_OPMAP_HALF ( 0x0 , 0x01 , 0x1f , 0xcf ) , /* 0x42: MBOX_GET_RESOURCE_COUNT */
2012-06-17 21:39:40 +00:00
ISP_FC_OPMAP ( 0x01 , 0x01 ) , /* 0x43: MBOX_REQUEST_OFFLINE_MODE */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x44: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x45: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x46: */
ISP_FC_OPMAP ( 0xcf , 0x03 ) , /* 0x47: GET PORT_DATABASE ENHANCED */
2015-10-20 10:16:03 +00:00
ISP_FC_OPMAP ( 0xcf , 0x0f ) , /* 0x48: MBOX_INIT_FIRMWARE_MULTI_ID */
2012-06-17 21:39:40 +00:00
ISP_FC_OPMAP ( 0xcd , 0x01 ) , /* 0x49: MBOX_GET_VP_DATABASE */
ISP_FC_OPMAP_HALF ( 0x2 , 0xcd , 0x0 , 0x01 ) , /* 0x4a: MBOX_GET_VP_DATABASE_ENTRY */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x4b: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x4c: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x4d: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x4e: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x4f: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x50: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x51: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x52: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x53: */
ISP_FC_OPMAP ( 0xcf , 0x01 ) , /* 0x54: EXECUTE IOCB A64 */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x55: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x56: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x57: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x58: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x59: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x5a: */
ISP_FC_OPMAP ( 0x03 , 0x01 ) , /* 0x5b: MBOX_DRIVER_HEARTBEAT */
ISP_FC_OPMAP ( 0xcf , 0x01 ) , /* 0x5c: MBOX_FW_HEARTBEAT */
2015-11-19 17:43:47 +00:00
ISP_FC_OPMAP ( 0x07 , 0x1f ) , /* 0x5d: MBOX_GET_SET_DATA_RATE */
2012-06-17 21:39:40 +00:00
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x5e: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x5f: */
2015-10-20 10:16:03 +00:00
ISP_FC_OPMAP ( 0xcf , 0x0f ) , /* 0x60: MBOX_INIT_FIRMWARE */
2012-06-17 21:39:40 +00:00
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x61: */
ISP_FC_OPMAP ( 0x01 , 0x01 ) , /* 0x62: MBOX_INIT_LIP */
ISP_FC_OPMAP ( 0xcd , 0x03 ) , /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */
ISP_FC_OPMAP ( 0xcf , 0x01 ) , /* 0x64: MBOX_GET_PORT_DB */
ISP_FC_OPMAP ( 0x07 , 0x01 ) , /* 0x65: MBOX_CLEAR_ACA */
ISP_FC_OPMAP ( 0x07 , 0x01 ) , /* 0x66: MBOX_TARGET_RESET */
ISP_FC_OPMAP ( 0x07 , 0x01 ) , /* 0x67: MBOX_CLEAR_TASK_SET */
ISP_FC_OPMAP ( 0x07 , 0x01 ) , /* 0x68: MBOX_ABORT_TASK_SET */
2018-02-28 16:24:32 +00:00
ISP_FC_OPMAP_HALF ( 0x00 , 0x01 , 0x0f , 0x1f ) , /* 0x69: MBOX_GET_FW_STATE */
2012-06-24 17:30:54 +00:00
ISP_FC_OPMAP_HALF ( 0x6 , 0x03 , 0x0 , 0xcf ) , /* 0x6a: MBOX_GET_PORT_NAME */
2012-06-17 21:39:40 +00:00
ISP_FC_OPMAP ( 0xcf , 0x01 ) , /* 0x6b: MBOX_GET_LINK_STATUS */
ISP_FC_OPMAP ( 0x0f , 0x01 ) , /* 0x6c: MBOX_INIT_LIP_RESET */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x6d: */
ISP_FC_OPMAP ( 0xcf , 0x03 ) , /* 0x6e: MBOX_SEND_SNS */
ISP_FC_OPMAP ( 0x0f , 0x07 ) , /* 0x6f: MBOX_FABRIC_LOGIN */
2015-11-22 17:03:38 +00:00
ISP_FC_OPMAP_HALF ( 0x02 , 0x03 , 0x00 , 0x03 ) , /* 0x70: MBOX_SEND_CHANGE_REQUEST */
2012-06-17 21:39:40 +00:00
ISP_FC_OPMAP ( 0x03 , 0x03 ) , /* 0x71: MBOX_FABRIC_LOGOUT */
ISP_FC_OPMAP ( 0x0f , 0x0f ) , /* 0x72: MBOX_INIT_LIP_LOGIN */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x73: */
ISP_FC_OPMAP ( 0x07 , 0x01 ) , /* 0x74: LOGIN LOOP PORT */
2015-10-28 12:34:59 +00:00
ISP_FC_OPMAP_HALF ( 0x03 , 0xcf , 0x00 , 0x07 ) , /* 0x75: GET PORT/NODE NAME LIST */
2012-06-17 21:39:40 +00:00
ISP_FC_OPMAP ( 0x4f , 0x01 ) , /* 0x76: SET VENDOR ID */
ISP_FC_OPMAP ( 0xcd , 0x01 ) , /* 0x77: INITIALIZE IP MAILBOX */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x78: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x79: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x7a: */
ISP_FC_OPMAP ( 0x00 , 0x00 ) , /* 0x7b: */
2015-10-28 12:34:59 +00:00
ISP_FC_OPMAP_HALF ( 0x03 , 0x4f , 0x00 , 0x07 ) , /* 0x7c: Get ID List */
2012-06-17 21:39:40 +00:00
ISP_FC_OPMAP ( 0xcf , 0x01 ) , /* 0x7d: SEND LFA */
ISP_FC_OPMAP ( 0x0f , 0x01 ) /* 0x7e: LUN RESET */
1998-04-22 17:54:58 +00:00
} ;
2012-06-17 21:39:40 +00:00
# define MAX_FC_OPCODE 0x7e
2002-02-17 06:38:22 +00:00
/*
* Footnotes
*
2009-08-01 01:04:26 +00:00
* ( 1 ) : this sets bits 21. .16 in mailbox register # 8 , which we nominally
2002-02-17 06:38:22 +00:00
* do not access at this time in the core driver . The caller is
2006-07-03 08:24:09 +00:00
* responsible for setting this register first ( Gross ! ) . The assumption
* is that we won ' t overflow .
2002-02-17 06:38:22 +00:00
*/
1998-04-22 17:54:58 +00:00
2007-03-22 23:38:32 +00:00
static const char * fc_mbcmd_names [ ] = {
2015-11-22 11:13:09 +00:00
" NO-OP " , /* 00h */
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
" LOAD RAM " ,
" EXEC FIRMWARE " ,
" DUMP RAM " ,
" WRITE RAM WORD " ,
" READ RAM WORD " ,
" MAILBOX REG TEST " ,
" VERIFY CHECKSUM " ,
" ABOUT FIRMWARE " ,
2011-11-16 02:52:24 +00:00
" LOAD RAM (2100) " ,
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
" DUMP RAM " ,
2011-11-16 02:52:24 +00:00
" LOAD RISC RAM " ,
2015-11-22 11:13:09 +00:00
" DUMP RISC RAM " ,
2011-11-16 02:52:24 +00:00
" WRITE RAM WORD EXTENDED " ,
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
" CHECK FIRMWARE " ,
2011-11-16 02:52:24 +00:00
" READ RAM WORD EXTENDED " ,
2015-11-22 11:13:09 +00:00
" INIT REQUEST QUEUE " , /* 10h */
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
" INIT RESULT QUEUE " ,
" EXECUTE IOCB " ,
" WAKE UP " ,
" STOP FIRMWARE " ,
" ABORT " ,
" ABORT DEVICE " ,
" ABORT TARGET " ,
" BUS RESET " ,
" STOP QUEUE " ,
" START QUEUE " ,
" SINGLE STEP QUEUE " ,
" ABORT QUEUE " ,
" GET DEV QUEUE STATUS " ,
NULL ,
" GET FIRMWARE STATUS " ,
2015-11-22 11:13:09 +00:00
" GET LOOP ID " , /* 20h */
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
NULL ,
2015-11-22 11:13:09 +00:00
" GET TIMEOUT PARAMS " ,
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
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
" GET FIRMWARE OPTIONS " ,
" GET PORT QUEUE PARAMS " ,
2015-11-22 11:13:09 +00:00
" GENERATE SYSTEM ERROR " ,
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
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
2015-11-22 11:13:09 +00:00
" WRITE SFP " , /* 30h */
" READ SFP " ,
" SET TIMEOUT PARAMS " ,
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
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
" SET FIRMWARE OPTIONS " ,
" SET PORT QUEUE PARAMS " ,
NULL ,
2015-11-22 11:13:09 +00:00
" SET FC LED CONF " ,
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
NULL ,
2015-11-22 11:13:09 +00:00
" RESTART NIC FIRMWARE " ,
" ACCESS CONTROL " ,
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
NULL ,
2015-11-22 11:13:09 +00:00
" LOOP PORT BYPASS " , /* 40h */
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
" LOOP PORT ENABLE " ,
2006-11-02 03:21:32 +00:00
" GET RESOURCE COUNT " ,
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
" REQUEST NON PARTICIPATING MODE " ,
2015-11-22 11:13:09 +00:00
" DIAGNOSTIC ECHO TEST " ,
" DIAGNOSTIC LOOPBACK " ,
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
NULL ,
2006-07-03 08:24:09 +00:00
" GET PORT DATABASE ENHANCED " ,
2009-08-01 01:04:26 +00:00
" INIT FIRMWARE MULTI ID " ,
" GET VP DATABASE " ,
" GET VP DATABASE ENTRY " ,
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
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
2015-11-22 11:13:09 +00:00
" GET FCF LIST " , /* 50h */
" GET DCBX PARAMETERS " ,
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
NULL ,
2015-11-22 11:13:09 +00:00
" HOST MEMORY COPY " ,
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
" EXECUTE IOCB A64 " ,
NULL ,
NULL ,
2015-11-22 11:13:09 +00:00
" SEND RNID " ,
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
NULL ,
2015-11-22 11:13:09 +00:00
" SET PARAMETERS " ,
" GET PARAMETERS " ,
2003-02-16 01:32:52 +00:00
" DRIVER HEARTBEAT " ,
2015-11-22 11:13:09 +00:00
" FIRMWARE HEARTBEAT " ,
2001-10-01 03:45:54 +00:00
" GET/SET DATA RATE " ,
2015-11-22 11:13:09 +00:00
" SEND RNFT " ,
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
NULL ,
2015-11-22 11:13:09 +00:00
" INIT FIRMWARE " , /* 60h */
" GET INIT CONTROL BLOCK " ,
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
" INIT LIP " ,
" GET FC-AL POSITION MAP " ,
" GET PORT DATABASE " ,
" CLEAR ACA " ,
" TARGET RESET " ,
" CLEAR TASK SET " ,
" ABORT TASK SET " ,
" GET FW STATE " ,
" GET PORT NAME " ,
" GET LINK STATUS " ,
" INIT LIP RESET " ,
2015-11-22 11:13:09 +00:00
" GET LINK STATS & PRIVATE DATA CNTS " ,
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
" SEND SNS " ,
" FABRIC LOGIN " ,
2015-11-22 11:13:09 +00:00
" SEND CHANGE REQUEST " , /* 70h */
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
" FABRIC LOGOUT " ,
" INIT LIP LOGIN " ,
NULL ,
" LOGIN LOOP PORT " ,
" GET PORT/NODE NAME LIST " ,
" SET VENDOR ID " ,
" INITIALIZE IP MAILBOX " ,
NULL ,
NULL ,
2015-11-22 11:13:09 +00:00
" GET XGMAC STATS " ,
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
NULL ,
2015-11-22 11:13:09 +00:00
" GET ID LIST " ,
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
" SEND LFA " ,
2015-11-22 11:13:09 +00:00
" LUN RESET "
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
} ;
1998-04-22 17:54:58 +00:00
static void
2006-11-02 03:21:32 +00:00
isp_mboxcmd ( ispsoftc_t * isp , mbreg_t * mbp )
1998-04-22 17:54:58 +00:00
{
2015-10-29 16:48:12 +00:00
const char * cname , * xname , * sname ;
2007-03-22 23:38:32 +00:00
char tname [ 16 ] , mname [ 16 ] ;
2020-11-24 15:32:25 +00:00
unsigned int ibits , obits , box , opcode , t , to ;
1998-04-22 17:54:58 +00:00
2012-06-17 21:39:40 +00:00
opcode = mbp - > param [ 0 ] ;
2020-11-20 01:15:48 +00:00
if ( opcode > MAX_FC_OPCODE ) {
mbp - > param [ 0 ] = MBOX_INVALID_COMMAND ;
isp_prt ( isp , ISP_LOGERR , " Unknown Command 0x%x " , opcode ) ;
return ;
1998-12-05 01:33:57 +00:00
}
2020-11-20 01:15:48 +00:00
cname = fc_mbcmd_names [ opcode ] ;
ibits = ISP_FC_IBITS ( opcode ) ;
obits = ISP_FC_OBITS ( opcode ) ;
2015-06-22 06:30:02 +00:00
if ( cname = = NULL ) {
cname = tname ;
ISP_SNPRINTF ( tname , sizeof tname , " opcode %x " , opcode ) ;
}
isp_prt ( isp , ISP_LOGDEBUG3 , " Mailbox Command '%s' " , cname ) ;
1998-12-05 01:33:57 +00:00
2006-07-03 08:24:09 +00:00
/*
* Pick up any additional bits that the caller might have set .
*/
2006-01-23 06:23:37 +00:00
ibits | = mbp - > ibits ;
obits | = mbp - > obits ;
1998-09-15 08:42:56 +00:00
2013-07-13 21:24:25 +00:00
/*
* Mask any bits that the caller wants us to mask
*/
ibits & = mbp - > ibitm ;
obits & = mbp - > obitm ;
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
if ( ibits = = 0 & & obits = = 0 ) {
mbp - > param [ 0 ] = MBOX_COMMAND_PARAM_ERROR ;
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
isp_prt ( isp , ISP_LOGERR , " no parameters for 0x%x " , opcode ) ;
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
return ;
1998-04-22 17:54:58 +00:00
}
2012-06-17 21:39:40 +00:00
for ( box = 0 ; box < ISP_NMBOX ( isp ) ; box + + ) {
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
if ( ibits & ( 1 < < box ) ) {
2009-08-01 01:04:26 +00:00
isp_prt ( isp , ISP_LOGDEBUG3 , " IN mbox %d = 0x%04x " , box ,
2006-07-16 20:11:50 +00:00
mbp - > param [ box ] ) ;
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
ISP_WRITE ( isp , MBOX_OFF ( box ) , mbp - > param [ box ] ) ;
1999-03-25 22:52:45 +00:00
}
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
isp - > isp_mboxtmp [ box ] = mbp - > param [ box ] = 0 ;
1998-04-22 17:54:58 +00:00
}
Major restructuring for swizzling to the request queue and unswizzling from
the response queue. Instead of the ad hoc ISP_SWIZZLE_REQUEST, we now have
a complete set of inline functions in isp_inline.h. Each platform is
responsible for providing just one of a set of ISP_IOX_{GET,PUT}{8,16,32}
macros.
The reason this needs to be done is that we need to have a single set of
functions that will work correctly on multiple architectures for both little
and big endian machines. It also needs to work correctly in the case that
we have the request or response queues in memory that has to be treated
specially (e.g., have ddi_dma_sync called on it for Solaris after we update
it or before we read from it). It also has to handle the SBus cards (for
platforms that have them) which, while on a Big Endian machine, do *not*
require *most* of the request/response queue entry fields to be swizzled
or unswizzled.
One thing that falls out of this is that we no longer build requests in the
request queue itself. Instead, we build the request locally (e.g., on the
stack) and then as part of the swizzling operation, copy it to the request
queue entry we've allocated. I thought long and hard about whether this was
too expensive a change to make as it in a lot of cases requires an extra
copy. On balance, the flexbility is worth it. With any luck, the entry that
we build locally stays in a processor writeback cache (after all, it's only
64 bytes) so that the cost of actually flushing it to the memory area that is
the shared queue with the PCI device is not all that expensive. We may examine
this again and try to get clever in the future to try and avoid copies.
Another change that falls out of this is that MEMORYBARRIER should be taken
a lot more seriously. The macro ISP_ADD_REQUEST does a MEMORYBARRIER on the
entry being added. But there had been many other places this had been missing.
It's now very important that it be done.
Additional changes:
Fix a longstanding buglet of sorts. When we get an entry via isp_getrqentry,
the iptr value that gets returned is the value we intend to eventually plug
into the ISP registers as the entry *one past* the last one we've written-
*not* the current entry we're updating. All along we've been calling sync
functions on the wrong index value. Argh. The 'fix' here is to rename all
'iptr' variables as 'nxti' to remember that this is the 'next' pointer-
not the current pointer.
Devote a single bit to mboxbsy- and set aside bits for output mbox registers
that we need to pick up- we can have at least one command which does not
have any defined output registers (MBOX_EXECUTE_FIRMWARE).
MFC after: 2 weeks
2001-12-11 00:18:45 +00:00
isp - > isp_obits = obits ;
isp - > isp_mboxbsy = 1 ;
1998-04-22 17:54:58 +00:00
/*
* Set Host Interrupt condition so that RISC will pick up mailbox regs .
*/
2020-11-20 01:15:48 +00:00
ISP_WRITE ( isp , BIU2400_HCCR , HCCR_2400_CMD_SET_HOST_INT ) ;
1998-04-22 17:54:58 +00:00
1999-03-17 05:04:39 +00:00
/*
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
* While we haven ' t finished the command , spin our wheels here .
1999-03-17 05:04:39 +00:00
*/
2020-11-24 15:32:25 +00:00
to = ( mbp - > timeout = = 0 ) ? MBCMD_DEFAULT_TIMEOUT : mbp - > timeout ;
for ( t = 0 ; t < to ; t + = 100 ) {
if ( ! isp - > isp_mboxbsy )
break ;
ISP_RUN_ISR ( isp ) ;
if ( ! isp - > isp_mboxbsy )
break ;
ISP_DELAY ( 100 ) ;
}
1998-04-22 17:54:58 +00:00
2006-07-03 08:24:09 +00:00
/*
* Did the command time out ?
*/
2020-11-24 15:32:25 +00:00
if ( isp - > isp_mboxbsy ) {
2009-08-01 01:04:26 +00:00
isp - > isp_mboxbsy = 0 ;
2020-11-24 15:32:25 +00:00
isp_prt ( isp , ISP_LOGWARN , " Mailbox Command (0x%x) Timeout (%uus) (%s:%d) " ,
2020-11-26 18:47:23 +00:00
opcode , to , mbp - > func , mbp - > lineno ) ;
2020-11-24 15:32:25 +00:00
mbp - > param [ 0 ] = MBOX_TIMEOUT ;
2006-11-02 03:21:32 +00:00
goto out ;
Major restructuring for swizzling to the request queue and unswizzling from
the response queue. Instead of the ad hoc ISP_SWIZZLE_REQUEST, we now have
a complete set of inline functions in isp_inline.h. Each platform is
responsible for providing just one of a set of ISP_IOX_{GET,PUT}{8,16,32}
macros.
The reason this needs to be done is that we need to have a single set of
functions that will work correctly on multiple architectures for both little
and big endian machines. It also needs to work correctly in the case that
we have the request or response queues in memory that has to be treated
specially (e.g., have ddi_dma_sync called on it for Solaris after we update
it or before we read from it). It also has to handle the SBus cards (for
platforms that have them) which, while on a Big Endian machine, do *not*
require *most* of the request/response queue entry fields to be swizzled
or unswizzled.
One thing that falls out of this is that we no longer build requests in the
request queue itself. Instead, we build the request locally (e.g., on the
stack) and then as part of the swizzling operation, copy it to the request
queue entry we've allocated. I thought long and hard about whether this was
too expensive a change to make as it in a lot of cases requires an extra
copy. On balance, the flexbility is worth it. With any luck, the entry that
we build locally stays in a processor writeback cache (after all, it's only
64 bytes) so that the cost of actually flushing it to the memory area that is
the shared queue with the PCI device is not all that expensive. We may examine
this again and try to get clever in the future to try and avoid copies.
Another change that falls out of this is that MEMORYBARRIER should be taken
a lot more seriously. The macro ISP_ADD_REQUEST does a MEMORYBARRIER on the
entry being added. But there had been many other places this had been missing.
It's now very important that it be done.
Additional changes:
Fix a longstanding buglet of sorts. When we get an entry via isp_getrqentry,
the iptr value that gets returned is the value we intend to eventually plug
into the ISP registers as the entry *one past* the last one we've written-
*not* the current entry we're updating. All along we've been calling sync
functions on the wrong index value. Argh. The 'fix' here is to rename all
'iptr' variables as 'nxti' to remember that this is the 'next' pointer-
not the current pointer.
Devote a single bit to mboxbsy- and set aside bits for output mbox registers
that we need to pick up- we can have at least one command which does not
have any defined output registers (MBOX_EXECUTE_FIRMWARE).
MFC after: 2 weeks
2001-12-11 00:18:45 +00:00
}
1998-04-22 17:54:58 +00:00
/*
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
* Copy back output registers .
1998-04-22 17:54:58 +00:00
*/
2012-06-17 21:39:40 +00:00
for ( box = 0 ; box < ISP_NMBOX ( isp ) ; box + + ) {
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
if ( obits & ( 1 < < box ) ) {
mbp - > param [ box ] = isp - > isp_mboxtmp [ box ] ;
2009-08-01 01:04:26 +00:00
isp_prt ( isp , ISP_LOGDEBUG3 , " OUT mbox %d = 0x%04x " , box ,
2006-07-16 20:11:50 +00:00
mbp - > param [ box ] ) ;
1999-05-11 05:06:55 +00:00
}
}
2015-10-29 16:48:12 +00:00
out :
if ( mbp - > logval = = 0 | | mbp - > param [ 0 ] = = MBOX_COMMAND_COMPLETE )
return ;
if ( ( mbp - > param [ 0 ] & 0xbfe0 ) = = 0 & &
( mbp - > logval & MBLOGMASK ( mbp - > param [ 0 ] ) ) = = 0 )
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
return ;
xname = NULL ;
2015-10-29 16:48:12 +00:00
sname = " " ;
1999-03-25 22:52:45 +00:00
switch ( mbp - > param [ 0 ] ) {
1998-04-22 17:54:58 +00:00
case MBOX_INVALID_COMMAND :
2015-10-29 16:48:12 +00:00
xname = " INVALID COMMAND " ;
1998-04-22 17:54:58 +00:00
break ;
case MBOX_HOST_INTERFACE_ERROR :
2015-10-29 16:48:12 +00:00
xname = " HOST INTERFACE ERROR " ;
1998-04-22 17:54:58 +00:00
break ;
case MBOX_TEST_FAILED :
2015-10-29 16:48:12 +00:00
xname = " TEST FAILED " ;
1998-04-22 17:54:58 +00:00
break ;
case MBOX_COMMAND_ERROR :
2015-10-29 16:48:12 +00:00
xname = " COMMAND ERROR " ;
ISP_SNPRINTF ( mname , sizeof ( mname ) , " subcode 0x%x " ,
mbp - > param [ 1 ] ) ;
sname = mname ;
1998-04-22 17:54:58 +00:00
break ;
case MBOX_COMMAND_PARAM_ERROR :
2015-10-29 16:48:12 +00:00
xname = " COMMAND PARAMETER ERROR " ;
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
break ;
2000-02-29 05:52:14 +00:00
case MBOX_PORT_ID_USED :
2015-10-29 16:48:12 +00:00
xname = " PORT ID ALREADY IN USE " ;
break ;
case MBOX_LOOP_ID_USED :
xname = " LOOP ID ALREADY IN USE " ;
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
break ;
2000-02-29 05:52:14 +00:00
case MBOX_ALL_IDS_USED :
2015-10-29 16:48:12 +00:00
xname = " ALL LOOP IDS IN USE " ;
break ;
case MBOX_NOT_LOGGED_IN :
xname = " NOT LOGGED IN " ;
break ;
case MBOX_LINK_DOWN_ERROR :
xname = " LINK DOWN ERROR " ;
break ;
case MBOX_LOOPBACK_ERROR :
xname = " LOOPBACK ERROR " ;
break ;
case MBOX_CHECKSUM_ERROR :
xname = " CHECKSUM ERROR " ;
break ;
case MBOX_INVALID_PRODUCT_KEY :
xname = " INVALID PRODUCT KEY " ;
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
break ;
2006-11-02 03:21:32 +00:00
case MBOX_REGS_BUSY :
xname = " REGISTERS BUSY " ;
break ;
case MBOX_TIMEOUT :
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
xname = " TIMEOUT " ;
2000-02-29 05:52:14 +00:00
break ;
1998-04-22 17:54:58 +00:00
default :
2009-08-01 01:04:26 +00:00
ISP_SNPRINTF ( mname , sizeof mname , " error 0x%x " , mbp - > param [ 0 ] ) ;
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
xname = mname ;
1998-04-22 17:54:58 +00:00
break ;
}
2006-07-14 05:14:48 +00:00
if ( xname ) {
2015-10-29 16:48:12 +00:00
isp_prt ( isp , ISP_LOGALL , " Mailbox Command '%s' failed (%s%s) " ,
cname , xname , sname ) ;
2006-07-14 05:14:48 +00:00
}
1998-04-22 17:54:58 +00:00
}
2015-11-17 16:33:46 +00:00
static int
2009-08-01 01:04:26 +00:00
isp_fw_state ( ispsoftc_t * isp , int chan )
1998-04-22 17:54:58 +00:00
{
mbreg_t mbs ;
2009-08-01 01:04:26 +00:00
2020-11-20 01:15:48 +00:00
MBSINIT ( & mbs , MBOX_GET_FW_STATE , MBLOGALL , 0 ) ;
isp_mboxcmd ( isp , & mbs ) ;
if ( mbs . param [ 0 ] = = MBOX_COMMAND_COMPLETE )
return ( mbs . param [ 1 ] ) ;
return ( FW_ERROR ) ;
1998-04-22 17:54:58 +00:00
}
2007-03-22 23:38:32 +00:00
static void
2009-08-01 01:04:26 +00:00
isp_setdfltfcparm ( ispsoftc_t * isp , int chan )
2007-03-22 23:38:32 +00:00
{
2009-08-01 01:04:26 +00:00
fcparam * fcp = FCPARAM ( isp , chan ) ;
2007-03-22 23:38:32 +00:00
2009-08-01 01:04:26 +00:00
/*
* Establish some default parameters .
*/
2015-11-23 10:06:19 +00:00
fcp - > role = DEFAULT_ROLE ( isp , chan ) ;
2007-03-22 23:38:32 +00:00
fcp - > isp_retry_delay = ICB_DFLT_RDELAY ;
fcp - > isp_retry_count = ICB_DFLT_RCOUNT ;
2009-08-01 01:04:26 +00:00
fcp - > isp_loopid = DEFAULT_LOOPID ( isp , chan ) ;
fcp - > isp_wwnn_nvram = DEFAULT_NODEWWN ( isp , chan ) ;
fcp - > isp_wwpn_nvram = DEFAULT_PORTWWN ( isp , chan ) ;
2007-03-22 23:38:32 +00:00
fcp - > isp_fwoptions = 0 ;
2015-12-03 22:55:40 +00:00
fcp - > isp_xfwoptions = 0 ;
fcp - > isp_zfwoptions = 0 ;
2009-08-01 01:04:26 +00:00
fcp - > isp_lasthdl = NIL_HANDLE ;
2016-04-13 10:35:17 +00:00
fcp - > isp_login_hdl = NIL_HANDLE ;
2009-08-01 01:04:26 +00:00
2020-11-20 01:15:48 +00:00
fcp - > isp_fwoptions | = ICB2400_OPT1_FAIRNESS ;
fcp - > isp_fwoptions | = ICB2400_OPT1_HARD_ADDRESS ;
if ( isp - > isp_confopts & ISP_CFG_FULL_DUPLEX )
fcp - > isp_fwoptions | = ICB2400_OPT1_FULL_DUPLEX ;
fcp - > isp_fwoptions | = ICB2400_OPT1_BOTH_WWNS ;
fcp - > isp_xfwoptions | = ICB2400_OPT2_LOOP_2_PTP ;
fcp - > isp_zfwoptions | = ICB2400_OPT3_RATE_AUTO ;
2007-03-22 23:38:32 +00:00
/*
* Now try and read NVRAM unless told to not do so .
* This will set fcparam ' s isp_wwnn_nvram & & isp_wwpn_nvram .
*/
if ( ( isp - > isp_confopts & ISP_CFG_NONVRAM ) = = 0 ) {
int i , j = 0 ;
/*
* Give a couple of tries at reading NVRAM .
*/
for ( i = 0 ; i < 2 ; i + + ) {
2009-08-01 01:04:26 +00:00
j = isp_read_nvram ( isp , chan ) ;
2007-03-22 23:38:32 +00:00
if ( j = = 0 ) {
break ;
}
}
if ( j ) {
isp - > isp_confopts | = ISP_CFG_NONVRAM ;
}
}
2009-08-01 01:04:26 +00:00
fcp - > isp_wwnn = ACTIVE_NODEWWN ( isp , chan ) ;
fcp - > isp_wwpn = ACTIVE_PORTWWN ( isp , chan ) ;
isp_prt ( isp , ISP_LOGCONFIG , " Chan %d 0x%08x%08x/0x%08x%08x Role %s " ,
chan , ( uint32_t ) ( fcp - > isp_wwnn > > 32 ) , ( uint32_t ) ( fcp - > isp_wwnn ) ,
( uint32_t ) ( fcp - > isp_wwpn > > 32 ) , ( uint32_t ) ( fcp - > isp_wwpn ) ,
isp_class3_roles [ fcp - > role ] ) ;
2007-03-22 23:38:32 +00:00
}
1999-03-25 22:52:45 +00:00
/*
1998-09-15 08:42:56 +00:00
* Re - initialize the ISP and complete all orphaned commands
1999-10-17 18:58:22 +00:00
* with a ' botched ' notice . The reset / init routines should
* not disturb an already active list of commands .
1998-09-15 08:42:56 +00:00
*/
2015-07-13 15:11:05 +00:00
int
2009-08-01 01:04:26 +00:00
isp_reinit ( ispsoftc_t * isp , int do_load_defaults )
1998-04-22 17:54:58 +00:00
{
2015-07-13 15:11:05 +00:00
int i , res = 0 ;
2009-08-01 01:04:26 +00:00
2017-03-14 08:03:56 +00:00
if ( isp - > isp_state > ISP_RESETSTATE )
isp_stop ( isp ) ;
2015-10-25 10:49:05 +00:00
if ( isp - > isp_state ! = ISP_RESETSTATE )
isp_reset ( isp , do_load_defaults ) ;
2001-02-11 03:44:43 +00:00
if ( isp - > isp_state ! = ISP_RESETSTATE ) {
2015-07-13 15:11:05 +00:00
res = EIO ;
2009-08-01 01:04:26 +00:00
isp_prt ( isp , ISP_LOGERR , " %s: cannot reset card " , __func__ ) ;
goto cleanup ;
}
isp_init ( isp ) ;
2015-10-25 10:49:05 +00:00
if ( isp - > isp_state > ISP_RESETSTATE & &
isp - > isp_state ! = ISP_RUNSTATE ) {
2015-07-13 15:11:05 +00:00
res = EIO ;
2015-10-25 10:49:05 +00:00
isp_prt ( isp , ISP_LOGERR , " %s: cannot init card " , __func__ ) ;
2006-11-02 03:21:32 +00:00
ISP_DISABLE_INTS ( isp ) ;
2015-07-13 15:11:05 +00:00
}
1998-04-22 17:54:58 +00:00
2015-11-19 17:43:47 +00:00
cleanup :
2009-08-01 01:04:26 +00:00
isp_clear_commands ( isp ) ;
2020-11-20 01:15:48 +00:00
for ( i = 0 ; i < isp - > isp_nchan ; i + + )
isp_clear_portdb ( isp , i ) ;
2015-07-13 15:11:05 +00:00
return ( res ) ;
1998-04-22 17:54:58 +00:00
}
1998-09-15 08:42:56 +00:00
/*
* NVRAM Routines
*/
static int
2009-08-01 01:04:26 +00:00
isp_read_nvram ( ispsoftc_t * isp , int bus )
1998-09-15 08:42:56 +00:00
{
2020-11-20 01:15:48 +00:00
return ( isp_read_nvram_2400 ( isp ) ) ;
1998-09-15 08:42:56 +00:00
}
2006-11-02 03:21:32 +00:00
static int
2020-11-20 01:15:48 +00:00
isp_read_nvram_2400 ( ispsoftc_t * isp )
2006-11-02 03:21:32 +00:00
{
int retval = 0 ;
uint32_t addr , csum , lwrds , * dptr ;
2020-11-20 01:15:48 +00:00
uint8_t nvram_data [ ISP2400_NVRAM_SIZE ] ;
2009-08-01 01:04:26 +00:00
2006-11-02 03:21:32 +00:00
if ( isp - > isp_port ) {
addr = ISP2400_NVRAM_PORT1_ADDR ;
} else {
addr = ISP2400_NVRAM_PORT0_ADDR ;
}
2009-08-01 01:04:26 +00:00
2006-11-02 03:21:32 +00:00
dptr = ( uint32_t * ) nvram_data ;
for ( lwrds = 0 ; lwrds < ISP2400_NVRAM_SIZE > > 2 ; lwrds + + ) {
isp_rd_2400_nvram ( isp , addr + + , dptr + + ) ;
}
if ( nvram_data [ 0 ] ! = ' I ' | | nvram_data [ 1 ] ! = ' S ' | |
nvram_data [ 2 ] ! = ' P ' ) {
2007-07-02 20:08:20 +00:00
isp_prt ( isp , ISP_LOGWARN , " invalid NVRAM header (%x %x %x) " ,
nvram_data [ 0 ] , nvram_data [ 1 ] , nvram_data [ 2 ] ) ;
2006-11-02 03:21:32 +00:00
retval = - 1 ;
goto out ;
}
dptr = ( uint32_t * ) nvram_data ;
for ( csum = 0 , lwrds = 0 ; lwrds < ISP2400_NVRAM_SIZE > > 2 ; lwrds + + ) {
2007-07-02 20:08:20 +00:00
uint32_t tmp ;
ISP_IOXGET_32 ( isp , & dptr [ lwrds ] , tmp ) ;
csum + = tmp ;
2006-11-02 03:21:32 +00:00
}
if ( csum ! = 0 ) {
isp_prt ( isp , ISP_LOGWARN , " invalid NVRAM checksum " ) ;
retval = - 1 ;
goto out ;
}
isp_parse_nvram_2400 ( isp , nvram_data ) ;
out :
return ( retval ) ;
}
static void
isp_rd_2400_nvram ( ispsoftc_t * isp , uint32_t addr , uint32_t * rp )
{
int loops = 0 ;
2009-08-01 01:04:26 +00:00
uint32_t base = 0x7ffe0000 ;
2007-03-12 04:54:30 +00:00
uint32_t tmp = 0 ;
2006-11-02 03:21:32 +00:00
2015-12-10 01:17:30 +00:00
if ( IS_26XX ( isp ) ) {
base = 0x7fe7c000 ; /* XXX: Observation, may be wrong. */
} else if ( IS_25XX ( isp ) ) {
2009-08-01 01:04:26 +00:00
base = 0x7ff00000 | 0x48000 ;
}
2006-11-02 03:21:32 +00:00
ISP_WRITE ( isp , BIU2400_FLASH_ADDR , base | addr ) ;
for ( loops = 0 ; loops < 5000 ; loops + + ) {
2009-08-01 01:04:26 +00:00
ISP_DELAY ( 10 ) ;
2006-11-02 03:21:32 +00:00
tmp = ISP_READ ( isp , BIU2400_FLASH_ADDR ) ;
2007-02-23 21:59:21 +00:00
if ( ( tmp & ( 1U < < 31 ) ) ! = 0 ) {
2006-11-02 03:21:32 +00:00
break ;
}
}
2007-02-23 21:59:21 +00:00
if ( tmp & ( 1U < < 31 ) ) {
2007-07-02 20:08:20 +00:00
* rp = ISP_READ ( isp , BIU2400_FLASH_DATA ) ;
ISP_SWIZZLE_NVRAM_LONG ( isp , rp ) ;
2006-11-02 03:21:32 +00:00
} else {
* rp = 0xffffffff ;
}
}
static void
isp_parse_nvram_2400 ( ispsoftc_t * isp , uint8_t * nvram_data )
{
2009-08-01 01:04:26 +00:00
fcparam * fcp = FCPARAM ( isp , 0 ) ;
2006-11-02 03:21:32 +00:00
uint64_t wwn ;
isp_prt ( isp , ISP_LOGDEBUG0 ,
2020-11-22 02:51:30 +00:00
" NVRAM 0x%08x%08x 0x%08x%08x maxframelen %d " ,
2006-11-02 03:21:32 +00:00
( uint32_t ) ( ISP2400_NVRAM_NODE_NAME ( nvram_data ) > > 32 ) ,
( uint32_t ) ( ISP2400_NVRAM_NODE_NAME ( nvram_data ) ) ,
( uint32_t ) ( ISP2400_NVRAM_PORT_NAME ( nvram_data ) > > 32 ) ,
( uint32_t ) ( ISP2400_NVRAM_PORT_NAME ( nvram_data ) ) ,
ISP2400_NVRAM_MAXFRAMELENGTH ( nvram_data ) ) ;
isp_prt ( isp , ISP_LOGDEBUG0 ,
2020-11-22 02:51:30 +00:00
" NVRAM loopid %d fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x " ,
2006-11-02 03:21:32 +00:00
ISP2400_NVRAM_HARDLOOPID ( nvram_data ) ,
ISP2400_NVRAM_FIRMWARE_OPTIONS1 ( nvram_data ) ,
ISP2400_NVRAM_FIRMWARE_OPTIONS2 ( nvram_data ) ,
ISP2400_NVRAM_FIRMWARE_OPTIONS3 ( nvram_data ) ) ;
wwn = ISP2400_NVRAM_PORT_NAME ( nvram_data ) ;
2007-01-20 04:00:21 +00:00
fcp - > isp_wwpn_nvram = wwn ;
2006-11-02 03:21:32 +00:00
wwn = ISP2400_NVRAM_NODE_NAME ( nvram_data ) ;
if ( wwn ) {
if ( ( wwn > > 60 ) ! = 2 & & ( wwn > > 60 ) ! = 5 ) {
wwn = 0 ;
}
}
2009-12-31 04:16:18 +00:00
if ( wwn = = 0 & & ( fcp - > isp_wwpn_nvram > > 60 ) = = 2 ) {
wwn = fcp - > isp_wwpn_nvram ;
wwn & = ~ ( ( uint64_t ) 0xfff < < 48 ) ;
}
2007-01-20 04:00:21 +00:00
fcp - > isp_wwnn_nvram = wwn ;
2006-11-02 03:21:32 +00:00
if ( ( isp - > isp_confopts & ISP_CFG_OWNFSZ ) = = 0 ) {
2009-08-01 01:04:26 +00:00
DEFAULT_FRAMESIZE ( isp ) =
ISP2400_NVRAM_MAXFRAMELENGTH ( nvram_data ) ;
2006-11-02 03:21:32 +00:00
}
if ( ( isp - > isp_confopts & ISP_CFG_OWNLOOPID ) = = 0 ) {
fcp - > isp_loopid = ISP2400_NVRAM_HARDLOOPID ( nvram_data ) ;
}
fcp - > isp_fwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS1 ( nvram_data ) ;
fcp - > isp_xfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS2 ( nvram_data ) ;
fcp - > isp_zfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS3 ( nvram_data ) ;
}