2005-01-06 01:43:34 +00:00
|
|
|
/*-
|
2006-01-23 06:23:37 +00:00
|
|
|
* Copyright (c) 1997-2006 by Matthew Jacob
|
|
|
|
* All rights reserved.
|
1998-04-22 17:54:58 +00:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice immediately at the beginning of the file, without modification,
|
|
|
|
* this list of conditions, and the following disclaimer.
|
2000-09-21 20:16:04 +00:00
|
|
|
* 2. The name of the author may not be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission.
|
1998-04-22 17:54:58 +00:00
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
|
|
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
2003-08-24 17:55:58 +00:00
|
|
|
|
2006-07-16 20:11:50 +00:00
|
|
|
/*
|
|
|
|
* Platform (FreeBSD) dependent common attachment code for Qlogic adapters.
|
|
|
|
*/
|
2003-08-24 17:55:58 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
1998-04-22 17:54:58 +00:00
|
|
|
#include <dev/isp/isp_freebsd.h>
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
#include <sys/unistd.h>
|
|
|
|
#include <sys/kthread.h>
|
2000-08-03 03:05:50 +00:00
|
|
|
#include <machine/stdarg.h> /* for use by isp_prt below */
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
#include <sys/conf.h>
|
2002-07-25 16:00:24 +00:00
|
|
|
#include <sys/module.h>
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
#include <sys/ioccom.h>
|
|
|
|
#include <dev/isp/isp_ioctl.h>
|
2006-09-26 04:59:52 +00:00
|
|
|
#if __FreeBSD_version >= 500000
|
|
|
|
#include <sys/sysctl.h>
|
2007-03-12 04:54:30 +00:00
|
|
|
#else
|
|
|
|
#include <sys/devicestat.h>
|
2006-09-26 04:59:52 +00:00
|
|
|
#endif
|
2006-11-14 08:45:48 +00:00
|
|
|
#include <cam/cam_periph.h>
|
2007-01-20 04:00:21 +00:00
|
|
|
#include <cam/cam_xpt_periph.h>
|
1998-04-22 17:54:58 +00:00
|
|
|
|
2006-12-18 23:50:30 +00:00
|
|
|
#if !defined(CAM_NEW_TRAN_CODE) && __FreeBSD_version >= 700025
|
|
|
|
#define CAM_NEW_TRAN_CODE 1
|
|
|
|
#endif
|
|
|
|
|
2001-04-04 21:58:29 +00:00
|
|
|
|
2002-07-25 16:00:24 +00:00
|
|
|
MODULE_VERSION(isp, 1);
|
2003-09-15 06:41:33 +00:00
|
|
|
MODULE_DEPEND(isp, cam, 1, 1, 1);
|
2002-07-11 03:25:04 +00:00
|
|
|
int isp_announced = 0;
|
2006-11-02 03:21:32 +00:00
|
|
|
int isp_fabric_hysteresis = 5;
|
|
|
|
int isp_loop_down_limit = 300; /* default loop down limit */
|
2006-11-14 08:45:48 +00:00
|
|
|
int isp_change_is_bad = 0; /* "changed" devices are bad */
|
|
|
|
int isp_quickboot_time = 15; /* don't wait more than N secs for loop up */
|
|
|
|
int isp_gone_device_time = 30; /* grace time before reporting device lost */
|
|
|
|
static const char *roles[4] = {
|
|
|
|
"(none)", "Target", "Initiator", "Target/Initiator"
|
|
|
|
};
|
|
|
|
static const char prom3[] =
|
|
|
|
"PortID 0x%06x Departed from Target %u because of %s";
|
2002-07-11 03:25:04 +00:00
|
|
|
|
2006-11-14 08:45:48 +00:00
|
|
|
static void isp_freeze_loopdown(ispsoftc_t *, char *);
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
static d_ioctl_t ispioctl;
|
2000-07-04 01:05:43 +00:00
|
|
|
static void isp_intr_enable(void *);
|
2006-02-15 00:31:48 +00:00
|
|
|
static void isp_cam_async(void *, uint32_t, struct cam_path *, void *);
|
1999-08-16 20:11:45 +00:00
|
|
|
static void isp_poll(struct cam_sim *);
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
static timeout_t isp_watchdog;
|
2006-11-14 08:45:48 +00:00
|
|
|
static timeout_t isp_ldt;
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
static void isp_kthread(void *);
|
2000-01-03 23:55:30 +00:00
|
|
|
static void isp_action(struct cam_sim *, union ccb *);
|
1999-08-16 20:11:45 +00:00
|
|
|
|
2006-09-01 04:57:14 +00:00
|
|
|
#if __FreeBSD_version < 700000
|
|
|
|
ispfwfunc *isp_get_firmware_p = NULL;
|
|
|
|
#endif
|
2000-05-09 01:08:21 +00:00
|
|
|
|
2006-04-21 18:30:01 +00:00
|
|
|
#if __FreeBSD_version < 500000
|
|
|
|
#define ISP_CDEV_MAJOR 248
|
|
|
|
static struct cdevsw isp_cdevsw = {
|
|
|
|
/* open */ nullopen,
|
|
|
|
/* close */ nullclose,
|
|
|
|
/* read */ noread,
|
|
|
|
/* write */ nowrite,
|
|
|
|
/* ioctl */ ispioctl,
|
|
|
|
/* poll */ nopoll,
|
|
|
|
/* mmap */ nommap,
|
|
|
|
/* strategy */ nostrategy,
|
|
|
|
/* name */ "isp",
|
|
|
|
/* maj */ ISP_CDEV_MAJOR,
|
|
|
|
/* dump */ nodump,
|
|
|
|
/* psize */ nopsize,
|
|
|
|
/* flags */ D_TAPE,
|
|
|
|
};
|
2006-09-26 04:59:52 +00:00
|
|
|
#define isp_sysctl_update(x) do { ; } while (0)
|
2006-04-21 18:30:01 +00:00
|
|
|
#else
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
static struct cdevsw isp_cdevsw = {
|
2004-02-21 21:10:55 +00:00
|
|
|
.d_version = D_VERSION,
|
2007-05-05 20:17:23 +00:00
|
|
|
#if __FreeBSD_version < 700037
|
2004-02-21 21:10:55 +00:00
|
|
|
.d_flags = D_NEEDGIANT,
|
2007-05-05 20:17:23 +00:00
|
|
|
#endif
|
2003-03-03 12:15:54 +00:00
|
|
|
.d_ioctl = ispioctl,
|
|
|
|
.d_name = "isp",
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
};
|
2006-09-26 04:59:52 +00:00
|
|
|
static void isp_sysctl_update(ispsoftc_t *);
|
2006-04-21 18:30:01 +00:00
|
|
|
#endif
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
|
2006-04-21 18:30:01 +00:00
|
|
|
static ispsoftc_t *isplist = NULL;
|
1998-09-15 08:42:56 +00:00
|
|
|
|
|
|
|
void
|
2006-04-21 18:30:01 +00:00
|
|
|
isp_attach(ispsoftc_t *isp)
|
1998-09-15 08:42:56 +00:00
|
|
|
{
|
1999-05-11 05:10:06 +00:00
|
|
|
int primary, secondary;
|
1998-09-15 08:42:56 +00:00
|
|
|
struct ccb_setasync csa;
|
|
|
|
struct cam_devq *devq;
|
1999-05-11 05:10:06 +00:00
|
|
|
struct cam_sim *sim;
|
|
|
|
struct cam_path *path;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Establish (in case of 12X0) which bus is the primary.
|
|
|
|
*/
|
|
|
|
|
|
|
|
primary = 0;
|
|
|
|
secondary = 1;
|
1998-09-15 08:42:56 +00:00
|
|
|
|
|
|
|
/*
|
1999-05-11 05:10:06 +00:00
|
|
|
* Create the device queue for our SIM(s).
|
1998-09-15 08:42:56 +00:00
|
|
|
*/
|
1999-10-17 18:50:47 +00:00
|
|
|
devq = cam_simq_alloc(isp->isp_maxcmds);
|
1998-09-15 08:42:56 +00:00
|
|
|
if (devq == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1999-05-11 05:10:06 +00:00
|
|
|
* Construct our SIM entry.
|
1998-09-15 08:42:56 +00:00
|
|
|
*/
|
2007-05-05 20:17:23 +00:00
|
|
|
sim = isp_sim_alloc(isp_action, isp_poll, "isp", isp,
|
|
|
|
device_get_unit(isp->isp_dev), 1, isp->isp_maxcmds, devq);
|
1999-05-11 05:10:06 +00:00
|
|
|
if (sim == NULL) {
|
1998-09-15 08:42:56 +00:00
|
|
|
cam_simq_free(devq);
|
|
|
|
return;
|
|
|
|
}
|
2000-07-04 01:05:43 +00:00
|
|
|
|
|
|
|
isp->isp_osinfo.ehook.ich_func = isp_intr_enable;
|
|
|
|
isp->isp_osinfo.ehook.ich_arg = isp;
|
2007-05-13 17:45:00 +00:00
|
|
|
ISP_UNLOCK(isp);
|
2000-07-04 01:05:43 +00:00
|
|
|
if (config_intrhook_establish(&isp->isp_osinfo.ehook) != 0) {
|
2007-05-13 17:45:00 +00:00
|
|
|
ISP_LOCK(isp);
|
2001-07-05 17:14:57 +00:00
|
|
|
cam_sim_free(sim, TRUE);
|
2000-12-05 07:39:54 +00:00
|
|
|
isp_prt(isp, ISP_LOGERR,
|
|
|
|
"could not establish interrupt enable hook");
|
2000-07-04 01:05:43 +00:00
|
|
|
return;
|
|
|
|
}
|
2007-05-13 17:45:00 +00:00
|
|
|
ISP_LOCK(isp);
|
2000-07-04 01:05:43 +00:00
|
|
|
|
2007-06-17 05:55:54 +00:00
|
|
|
if (xpt_bus_register(sim, isp->isp_dev, primary) != CAM_SUCCESS) {
|
1999-05-11 05:10:06 +00:00
|
|
|
cam_sim_free(sim, TRUE);
|
1998-09-15 08:42:56 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-05-11 05:10:06 +00:00
|
|
|
if (xpt_create_path(&path, NULL, cam_sim_path(sim),
|
1998-09-15 08:42:56 +00:00
|
|
|
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
1999-05-11 05:10:06 +00:00
|
|
|
xpt_bus_deregister(cam_sim_path(sim));
|
|
|
|
cam_sim_free(sim, TRUE);
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
config_intrhook_disestablish(&isp->isp_osinfo.ehook);
|
1998-09-15 08:42:56 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-05-11 05:10:06 +00:00
|
|
|
xpt_setup_ccb(&csa.ccb_h, path, 5);
|
1998-09-15 08:42:56 +00:00
|
|
|
csa.ccb_h.func_code = XPT_SASYNC_CB;
|
|
|
|
csa.event_enable = AC_LOST_DEVICE;
|
1999-01-30 07:29:00 +00:00
|
|
|
csa.callback = isp_cam_async;
|
1999-05-11 05:10:06 +00:00
|
|
|
csa.callback_arg = sim;
|
1998-09-15 08:42:56 +00:00
|
|
|
xpt_action((union ccb *)&csa);
|
1999-05-11 05:10:06 +00:00
|
|
|
isp->isp_sim = sim;
|
|
|
|
isp->isp_path = path;
|
1998-09-15 08:42:56 +00:00
|
|
|
|
1999-05-11 05:10:06 +00:00
|
|
|
/*
|
|
|
|
* If we have a second channel, construct SIM entry for that.
|
|
|
|
*/
|
1999-12-16 05:42:02 +00:00
|
|
|
if (IS_DUALBUS(isp)) {
|
2007-05-05 20:17:23 +00:00
|
|
|
sim = isp_sim_alloc(isp_action, isp_poll, "isp", isp,
|
|
|
|
device_get_unit(isp->isp_dev), 1, isp->isp_maxcmds, devq);
|
1999-05-11 05:10:06 +00:00
|
|
|
if (sim == NULL) {
|
|
|
|
xpt_bus_deregister(cam_sim_path(isp->isp_sim));
|
|
|
|
xpt_free_path(isp->isp_path);
|
|
|
|
cam_simq_free(devq);
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
config_intrhook_disestablish(&isp->isp_osinfo.ehook);
|
1999-05-11 05:10:06 +00:00
|
|
|
return;
|
|
|
|
}
|
2007-06-17 05:55:54 +00:00
|
|
|
if (xpt_bus_register(sim, isp->isp_dev, secondary) !=
|
|
|
|
CAM_SUCCESS) {
|
1999-05-11 05:10:06 +00:00
|
|
|
xpt_bus_deregister(cam_sim_path(isp->isp_sim));
|
|
|
|
xpt_free_path(isp->isp_path);
|
|
|
|
cam_sim_free(sim, TRUE);
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
config_intrhook_disestablish(&isp->isp_osinfo.ehook);
|
1999-05-11 05:10:06 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xpt_create_path(&path, NULL, cam_sim_path(sim),
|
|
|
|
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
|
|
|
xpt_bus_deregister(cam_sim_path(isp->isp_sim));
|
|
|
|
xpt_free_path(isp->isp_path);
|
|
|
|
xpt_bus_deregister(cam_sim_path(sim));
|
|
|
|
cam_sim_free(sim, TRUE);
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
config_intrhook_disestablish(&isp->isp_osinfo.ehook);
|
1999-05-11 05:10:06 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
xpt_setup_ccb(&csa.ccb_h, path, 5);
|
|
|
|
csa.ccb_h.func_code = XPT_SASYNC_CB;
|
|
|
|
csa.event_enable = AC_LOST_DEVICE;
|
|
|
|
csa.callback = isp_cam_async;
|
|
|
|
csa.callback_arg = sim;
|
|
|
|
xpt_action((union ccb *)&csa);
|
|
|
|
isp->isp_sim2 = sim;
|
|
|
|
isp->isp_path2 = path;
|
|
|
|
}
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Create device nodes
|
|
|
|
*/
|
2007-05-05 20:17:23 +00:00
|
|
|
ISP_UNLOCK(isp);
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
(void) make_dev(&isp_cdevsw, device_get_unit(isp->isp_dev), UID_ROOT,
|
|
|
|
GID_OPERATOR, 0600, "%s", device_get_nameunit(isp->isp_dev));
|
2007-05-05 20:17:23 +00:00
|
|
|
isp_sysctl_update(isp);
|
|
|
|
ISP_LOCK(isp);
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
|
2001-02-11 03:47:39 +00:00
|
|
|
if (isp->isp_role != ISP_ROLE_NONE) {
|
|
|
|
isp->isp_state = ISP_RUNSTATE;
|
2006-11-02 03:21:32 +00:00
|
|
|
ISP_ENABLE_INTS(isp);
|
2001-02-11 03:47:39 +00:00
|
|
|
}
|
2000-01-03 23:55:30 +00:00
|
|
|
if (isplist == NULL) {
|
|
|
|
isplist = isp;
|
|
|
|
} else {
|
2006-04-21 18:30:01 +00:00
|
|
|
ispsoftc_t *tmp = isplist;
|
2000-01-03 23:55:30 +00:00
|
|
|
while (tmp->isp_osinfo.next) {
|
|
|
|
tmp = tmp->isp_osinfo.next;
|
|
|
|
}
|
|
|
|
tmp->isp_osinfo.next = isp;
|
|
|
|
}
|
2007-05-05 20:17:23 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Create a kernel thread for fibre channel instances.
|
|
|
|
*/
|
|
|
|
if (IS_FC(isp)) {
|
|
|
|
isp_callout_init(&isp->isp_osinfo.ldt);
|
|
|
|
isp_callout_init(&isp->isp_osinfo.gdt);
|
|
|
|
ISP_UNLOCK(isp);
|
|
|
|
#if __FreeBSD_version >= 500000
|
2007-10-20 23:23:23 +00:00
|
|
|
if (kproc_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
|
2007-05-05 20:17:23 +00:00
|
|
|
RFHIGHPID, 0, "%s: fc_thrd",
|
|
|
|
device_get_nameunit(isp->isp_dev)))
|
|
|
|
#else
|
2007-10-20 23:23:23 +00:00
|
|
|
if (kproc_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
|
2007-05-05 20:17:23 +00:00
|
|
|
"%s: fc_thrd", device_get_nameunit(isp->isp_dev)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
ISP_LOCK(isp);
|
|
|
|
xpt_bus_deregister(cam_sim_path(sim));
|
|
|
|
cam_sim_free(sim, TRUE);
|
|
|
|
config_intrhook_disestablish(&isp->isp_osinfo.ehook);
|
|
|
|
isp_prt(isp, ISP_LOGERR, "could not create kthread");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ISP_LOCK(isp);
|
|
|
|
/*
|
|
|
|
* We start by being "loop down" if we have an initiator role
|
|
|
|
*/
|
|
|
|
if (isp->isp_role & ISP_ROLE_INITIATOR) {
|
|
|
|
isp_freeze_loopdown(isp, "isp_attach");
|
|
|
|
isp->isp_osinfo.ldt_running = 1;
|
|
|
|
callout_reset(&isp->isp_osinfo.ldt,
|
|
|
|
isp_quickboot_time * hz, isp_ldt, isp);
|
|
|
|
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
|
|
|
|
"Starting Initial Loop Down Timer");
|
|
|
|
}
|
|
|
|
}
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
}
|
|
|
|
|
2006-11-14 08:45:48 +00:00
|
|
|
static void
|
2006-04-21 18:30:01 +00:00
|
|
|
isp_freeze_loopdown(ispsoftc_t *isp, char *msg)
|
2002-07-08 17:42:47 +00:00
|
|
|
{
|
|
|
|
if (isp->isp_osinfo.simqfrozen == 0) {
|
|
|
|
isp_prt(isp, ISP_LOGDEBUG0, "%s: freeze simq (loopdown)", msg);
|
|
|
|
isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
|
|
|
|
xpt_freeze_simq(isp->isp_sim, 1);
|
|
|
|
} else {
|
|
|
|
isp_prt(isp, ISP_LOGDEBUG0, "%s: mark frozen (loopdown)", msg);
|
|
|
|
isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-21 18:30:01 +00:00
|
|
|
|
|
|
|
#if __FreeBSD_version < 500000
|
|
|
|
#define _DEV dev_t
|
|
|
|
#define _IOP struct proc
|
|
|
|
#else
|
|
|
|
#define _IOP struct thread
|
|
|
|
#define _DEV struct cdev *
|
|
|
|
#endif
|
|
|
|
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
static int
|
2006-04-21 18:30:01 +00:00
|
|
|
ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
{
|
2006-04-21 18:30:01 +00:00
|
|
|
ispsoftc_t *isp;
|
2004-02-07 03:47:33 +00:00
|
|
|
int nr, retval = ENOTTY;
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
|
|
|
|
isp = isplist;
|
|
|
|
while (isp) {
|
2008-09-27 08:51:18 +00:00
|
|
|
if (dev2unit(dev) == device_get_unit(isp->isp_dev)) {
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
isp = isp->isp_osinfo.next;
|
|
|
|
}
|
2007-05-05 20:17:23 +00:00
|
|
|
if (isp == NULL) {
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
return (ENXIO);
|
2007-05-05 20:17:23 +00:00
|
|
|
}
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
|
2006-03-03 07:04:43 +00:00
|
|
|
switch (c) {
|
2002-02-18 00:00:34 +00:00
|
|
|
#ifdef ISP_FW_CRASH_DUMP
|
|
|
|
case ISP_GET_FW_CRASH_DUMP:
|
2006-07-10 22:39:32 +00:00
|
|
|
if (IS_FC(isp)) {
|
|
|
|
uint16_t *ptr = FCPARAM(isp)->isp_dump_data;
|
|
|
|
size_t sz;
|
2002-02-18 00:00:34 +00:00
|
|
|
|
2006-07-10 22:39:32 +00:00
|
|
|
retval = 0;
|
|
|
|
if (IS_2200(isp)) {
|
|
|
|
sz = QLA2200_RISC_IMAGE_DUMP_SIZE;
|
2002-02-18 00:00:34 +00:00
|
|
|
} else {
|
2006-07-10 22:39:32 +00:00
|
|
|
sz = QLA2300_RISC_IMAGE_DUMP_SIZE;
|
2002-02-18 00:00:34 +00:00
|
|
|
}
|
2006-07-10 22:39:32 +00:00
|
|
|
if (ptr && *ptr) {
|
|
|
|
void *uaddr = *((void **) addr);
|
|
|
|
if (copyout(ptr, uaddr, sz)) {
|
|
|
|
retval = EFAULT;
|
|
|
|
} else {
|
|
|
|
*ptr = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
retval = ENXIO;
|
|
|
|
}
|
2002-02-18 00:00:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISP_FORCE_CRASH_DUMP:
|
2006-07-10 22:39:32 +00:00
|
|
|
if (IS_FC(isp)) {
|
2007-06-11 19:15:49 +00:00
|
|
|
ISP_LOCK(isp);
|
2006-07-10 22:39:32 +00:00
|
|
|
isp_freeze_loopdown(isp,
|
|
|
|
"ispioctl(ISP_FORCE_CRASH_DUMP)");
|
|
|
|
isp_fw_dump(isp);
|
|
|
|
isp_reinit(isp);
|
2007-06-11 19:15:49 +00:00
|
|
|
ISP_UNLOCK(isp);
|
2006-07-10 22:39:32 +00:00
|
|
|
retval = 0;
|
|
|
|
}
|
2002-02-18 00:00:34 +00:00
|
|
|
break;
|
|
|
|
#endif
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
case ISP_SDBLEV:
|
|
|
|
{
|
|
|
|
int olddblev = isp->isp_dblev;
|
|
|
|
isp->isp_dblev = *(int *)addr;
|
|
|
|
*(int *)addr = olddblev;
|
|
|
|
retval = 0;
|
|
|
|
break;
|
|
|
|
}
|
2004-02-07 03:47:33 +00:00
|
|
|
case ISP_GETROLE:
|
|
|
|
*(int *)addr = isp->isp_role;
|
|
|
|
retval = 0;
|
|
|
|
break;
|
|
|
|
case ISP_SETROLE:
|
|
|
|
nr = *(int *)addr;
|
|
|
|
if (nr & ~(ISP_ROLE_INITIATOR|ISP_ROLE_TARGET)) {
|
|
|
|
retval = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*(int *)addr = isp->isp_role;
|
|
|
|
isp->isp_role = nr;
|
|
|
|
/* FALLTHROUGH */
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
case ISP_RESETHBA:
|
2007-06-11 19:15:49 +00:00
|
|
|
ISP_LOCK(isp);
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
isp_reinit(isp);
|
2007-06-11 19:15:49 +00:00
|
|
|
ISP_UNLOCK(isp);
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
retval = 0;
|
|
|
|
break;
|
2002-02-21 23:30:05 +00:00
|
|
|
case ISP_RESCAN:
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
if (IS_FC(isp)) {
|
2007-06-11 19:15:49 +00:00
|
|
|
ISP_LOCK(isp);
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
if (isp_fc_runstate(isp, 5 * 1000000)) {
|
|
|
|
retval = EIO;
|
|
|
|
} else {
|
|
|
|
retval = 0;
|
|
|
|
}
|
2007-06-11 19:15:49 +00:00
|
|
|
ISP_UNLOCK(isp);
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISP_FC_LIP:
|
|
|
|
if (IS_FC(isp)) {
|
2007-06-11 19:15:49 +00:00
|
|
|
ISP_LOCK(isp);
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
if (isp_control(isp, ISPCTL_SEND_LIP, 0)) {
|
|
|
|
retval = EIO;
|
|
|
|
} else {
|
|
|
|
retval = 0;
|
|
|
|
}
|
2007-06-11 19:15:49 +00:00
|
|
|
ISP_UNLOCK(isp);
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISP_FC_GETDINFO:
|
|
|
|
{
|
|
|
|
struct isp_fc_device *ifc = (struct isp_fc_device *) addr;
|
2006-11-02 03:21:32 +00:00
|
|
|
fcportdb_t *lp;
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
|
2006-07-10 22:39:32 +00:00
|
|
|
if (IS_SCSI(isp)) {
|
|
|
|
break;
|
|
|
|
}
|
2007-07-10 07:55:59 +00:00
|
|
|
if (ifc->loopid >= MAX_FC_TARG) {
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
retval = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
lp = &FCPARAM(isp)->portdb[ifc->loopid];
|
2006-11-02 03:21:32 +00:00
|
|
|
if (lp->state == FC_PORTDB_STATE_VALID) {
|
2006-02-26 22:40:56 +00:00
|
|
|
ifc->role = lp->roles;
|
2006-11-02 03:21:32 +00:00
|
|
|
ifc->loopid = lp->handle;
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
ifc->portid = lp->portid;
|
|
|
|
ifc->node_wwn = lp->node_wwn;
|
|
|
|
ifc->port_wwn = lp->port_wwn;
|
|
|
|
retval = 0;
|
|
|
|
} else {
|
|
|
|
retval = ENODEV;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2002-01-03 20:43:22 +00:00
|
|
|
case ISP_GET_STATS:
|
|
|
|
{
|
|
|
|
isp_stats_t *sp = (isp_stats_t *) addr;
|
|
|
|
|
|
|
|
MEMZERO(sp, sizeof (*sp));
|
|
|
|
sp->isp_stat_version = ISP_STATS_VERSION;
|
|
|
|
sp->isp_type = isp->isp_type;
|
|
|
|
sp->isp_revision = isp->isp_revision;
|
2007-06-11 19:15:49 +00:00
|
|
|
ISP_LOCK(isp);
|
2002-01-03 20:43:22 +00:00
|
|
|
sp->isp_stats[ISP_INTCNT] = isp->isp_intcnt;
|
|
|
|
sp->isp_stats[ISP_INTBOGUS] = isp->isp_intbogus;
|
|
|
|
sp->isp_stats[ISP_INTMBOXC] = isp->isp_intmboxc;
|
|
|
|
sp->isp_stats[ISP_INGOASYNC] = isp->isp_intoasync;
|
|
|
|
sp->isp_stats[ISP_RSLTCCMPLT] = isp->isp_rsltccmplt;
|
|
|
|
sp->isp_stats[ISP_FPHCCMCPLT] = isp->isp_fphccmplt;
|
|
|
|
sp->isp_stats[ISP_RSCCHIWAT] = isp->isp_rscchiwater;
|
|
|
|
sp->isp_stats[ISP_FPCCHIWAT] = isp->isp_fpcchiwater;
|
2007-06-11 19:15:49 +00:00
|
|
|
ISP_UNLOCK(isp);
|
2002-01-03 20:43:22 +00:00
|
|
|
retval = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISP_CLR_STATS:
|
2007-06-11 19:15:49 +00:00
|
|
|
ISP_LOCK(isp);
|
2002-01-03 20:43:22 +00:00
|
|
|
isp->isp_intcnt = 0;
|
|
|
|
isp->isp_intbogus = 0;
|
|
|
|
isp->isp_intmboxc = 0;
|
|
|
|
isp->isp_intoasync = 0;
|
|
|
|
isp->isp_rsltccmplt = 0;
|
|
|
|
isp->isp_fphccmplt = 0;
|
|
|
|
isp->isp_rscchiwater = 0;
|
|
|
|
isp->isp_fpcchiwater = 0;
|
2007-06-11 19:15:49 +00:00
|
|
|
ISP_UNLOCK(isp);
|
2002-01-03 20:43:22 +00:00
|
|
|
retval = 0;
|
|
|
|
break;
|
2002-06-16 05:08:02 +00:00
|
|
|
case ISP_FC_GETHINFO:
|
|
|
|
{
|
|
|
|
struct isp_hba_device *hba = (struct isp_hba_device *) addr;
|
|
|
|
MEMZERO(hba, sizeof (*hba));
|
2006-07-10 22:39:32 +00:00
|
|
|
|
2004-01-23 23:22:11 +00:00
|
|
|
hba->fc_fw_major = ISP_FW_MAJORX(isp->isp_fwrev);
|
|
|
|
hba->fc_fw_minor = ISP_FW_MINORX(isp->isp_fwrev);
|
|
|
|
hba->fc_fw_micro = ISP_FW_MICROX(isp->isp_fwrev);
|
2006-07-10 22:39:32 +00:00
|
|
|
if (IS_FC(isp)) {
|
|
|
|
hba->fc_speed = FCPARAM(isp)->isp_gbspeed;
|
|
|
|
hba->fc_scsi_supported = 1;
|
|
|
|
hba->fc_topology = FCPARAM(isp)->isp_topo + 1;
|
|
|
|
hba->fc_loopid = FCPARAM(isp)->isp_loopid;
|
2007-01-20 04:00:21 +00:00
|
|
|
hba->nvram_node_wwn = FCPARAM(isp)->isp_wwnn_nvram;
|
|
|
|
hba->nvram_port_wwn = FCPARAM(isp)->isp_wwpn_nvram;
|
2006-07-10 22:39:32 +00:00
|
|
|
hba->active_node_wwn = ISP_NODEWWN(isp);
|
|
|
|
hba->active_port_wwn = ISP_PORTWWN(isp);
|
|
|
|
}
|
2002-06-16 05:08:02 +00:00
|
|
|
retval = 0;
|
|
|
|
break;
|
|
|
|
}
|
2005-10-29 02:46:59 +00:00
|
|
|
case ISP_TSK_MGMT:
|
|
|
|
{
|
|
|
|
int needmarker;
|
|
|
|
struct isp_fc_tsk_mgmt *fct = (struct isp_fc_tsk_mgmt *) addr;
|
2006-02-15 00:31:48 +00:00
|
|
|
uint16_t loopid;
|
2005-10-29 02:46:59 +00:00
|
|
|
mbreg_t mbs;
|
|
|
|
|
|
|
|
if (IS_SCSI(isp)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&mbs, 0, sizeof (mbs));
|
|
|
|
needmarker = retval = 0;
|
2006-01-23 06:23:37 +00:00
|
|
|
loopid = fct->loopid;
|
2006-11-02 03:21:32 +00:00
|
|
|
if (FCPARAM(isp)->isp_2klogin == 0) {
|
2006-01-23 06:23:37 +00:00
|
|
|
loopid <<= 8;
|
|
|
|
}
|
2005-10-29 02:46:59 +00:00
|
|
|
switch (fct->action) {
|
2006-08-04 20:14:03 +00:00
|
|
|
case IPT_CLEAR_ACA:
|
2005-10-29 02:46:59 +00:00
|
|
|
mbs.param[0] = MBOX_CLEAR_ACA;
|
2006-01-23 06:23:37 +00:00
|
|
|
mbs.param[1] = loopid;
|
2005-10-29 02:46:59 +00:00
|
|
|
mbs.param[2] = fct->lun;
|
|
|
|
break;
|
2006-08-04 20:14:03 +00:00
|
|
|
case IPT_TARGET_RESET:
|
2005-10-29 02:46:59 +00:00
|
|
|
mbs.param[0] = MBOX_TARGET_RESET;
|
2006-01-23 06:23:37 +00:00
|
|
|
mbs.param[1] = loopid;
|
2005-10-29 02:46:59 +00:00
|
|
|
needmarker = 1;
|
|
|
|
break;
|
2006-08-04 20:14:03 +00:00
|
|
|
case IPT_LUN_RESET:
|
2005-10-29 02:46:59 +00:00
|
|
|
mbs.param[0] = MBOX_LUN_RESET;
|
2006-01-23 06:23:37 +00:00
|
|
|
mbs.param[1] = loopid;
|
2005-10-29 02:46:59 +00:00
|
|
|
mbs.param[2] = fct->lun;
|
|
|
|
needmarker = 1;
|
|
|
|
break;
|
2006-08-04 20:14:03 +00:00
|
|
|
case IPT_CLEAR_TASK_SET:
|
2005-10-29 02:46:59 +00:00
|
|
|
mbs.param[0] = MBOX_CLEAR_TASK_SET;
|
2006-01-23 06:23:37 +00:00
|
|
|
mbs.param[1] = loopid;
|
2005-10-29 02:46:59 +00:00
|
|
|
mbs.param[2] = fct->lun;
|
|
|
|
needmarker = 1;
|
|
|
|
break;
|
2006-08-04 20:14:03 +00:00
|
|
|
case IPT_ABORT_TASK_SET:
|
2005-10-29 02:46:59 +00:00
|
|
|
mbs.param[0] = MBOX_ABORT_TASK_SET;
|
2006-01-23 06:23:37 +00:00
|
|
|
mbs.param[1] = loopid;
|
2005-10-29 02:46:59 +00:00
|
|
|
mbs.param[2] = fct->lun;
|
|
|
|
needmarker = 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
retval = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (retval == 0) {
|
|
|
|
if (needmarker) {
|
|
|
|
isp->isp_sendmarker |= 1;
|
|
|
|
}
|
2007-06-11 19:15:49 +00:00
|
|
|
ISP_LOCK(isp);
|
2005-10-29 02:46:59 +00:00
|
|
|
retval = isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
|
2007-06-11 19:15:49 +00:00
|
|
|
ISP_UNLOCK(isp);
|
2005-10-29 02:46:59 +00:00
|
|
|
if (retval)
|
|
|
|
retval = EIO;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return (retval);
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
|
|
|
|
2006-09-26 04:59:52 +00:00
|
|
|
#if __FreeBSD_version >= 500000
|
|
|
|
static void
|
|
|
|
isp_sysctl_update(ispsoftc_t *isp)
|
|
|
|
{
|
|
|
|
struct sysctl_ctx_list *ctx =
|
|
|
|
device_get_sysctl_ctx(isp->isp_osinfo.dev);
|
|
|
|
struct sysctl_oid *tree = device_get_sysctl_tree(isp->isp_osinfo.dev);
|
|
|
|
|
|
|
|
if (IS_SCSI(isp)) {
|
|
|
|
return;
|
|
|
|
}
|
2006-11-14 08:45:48 +00:00
|
|
|
|
2006-09-26 04:59:52 +00:00
|
|
|
snprintf(isp->isp_osinfo.sysctl_info.fc.wwnn,
|
|
|
|
sizeof (isp->isp_osinfo.sysctl_info.fc.wwnn), "0x%08x%08x",
|
|
|
|
(uint32_t) (ISP_NODEWWN(isp) >> 32), (uint32_t) ISP_NODEWWN(isp));
|
|
|
|
|
|
|
|
snprintf(isp->isp_osinfo.sysctl_info.fc.wwpn,
|
|
|
|
sizeof (isp->isp_osinfo.sysctl_info.fc.wwpn), "0x%08x%08x",
|
|
|
|
(uint32_t) (ISP_PORTWWN(isp) >> 32), (uint32_t) ISP_PORTWWN(isp));
|
|
|
|
|
|
|
|
SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
|
|
"wwnn", CTLFLAG_RD, isp->isp_osinfo.sysctl_info.fc.wwnn, 0,
|
|
|
|
"World Wide Node Name");
|
2006-11-14 08:45:48 +00:00
|
|
|
|
2006-09-26 04:59:52 +00:00
|
|
|
SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
|
|
"wwpn", CTLFLAG_RD, isp->isp_osinfo.sysctl_info.fc.wwpn, 0,
|
|
|
|
"World Wide Port Name");
|
2006-11-14 08:45:48 +00:00
|
|
|
|
|
|
|
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
|
|
"loop_down_limit",
|
|
|
|
CTLFLAG_RW, &isp->isp_osinfo.loop_down_limit, 0,
|
|
|
|
"How long to wait for loop to come back up");
|
|
|
|
|
|
|
|
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
|
|
"gone_device_time",
|
|
|
|
CTLFLAG_RW, &isp->isp_osinfo.gone_device_time, 0,
|
|
|
|
"How long to wait for a device to reappear");
|
2006-09-26 04:59:52 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2000-07-04 01:05:43 +00:00
|
|
|
static void
|
|
|
|
isp_intr_enable(void *arg)
|
|
|
|
{
|
2006-04-21 18:30:01 +00:00
|
|
|
ispsoftc_t *isp = arg;
|
2007-05-05 20:17:23 +00:00
|
|
|
ISP_LOCK(isp);
|
2001-02-11 03:47:39 +00:00
|
|
|
if (isp->isp_role != ISP_ROLE_NONE) {
|
2006-11-02 03:21:32 +00:00
|
|
|
ISP_ENABLE_INTS(isp);
|
2001-02-11 03:47:39 +00:00
|
|
|
}
|
2007-05-05 20:17:23 +00:00
|
|
|
ISP_UNLOCK(isp);
|
2000-07-04 01:05:43 +00:00
|
|
|
/* Release our hook so that the boot can continue. */
|
|
|
|
config_intrhook_disestablish(&isp->isp_osinfo.ehook);
|
|
|
|
}
|
2000-01-03 23:55:30 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Put the target mode functions here, because some are inlines
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef ISP_TARGET_MODE
|
|
|
|
|
2006-04-21 18:30:01 +00:00
|
|
|
static __inline int is_lun_enabled(ispsoftc_t *, int, lun_id_t);
|
|
|
|
static __inline int are_any_luns_enabled(ispsoftc_t *, int);
|
|
|
|
static __inline tstate_t *get_lun_statep(ispsoftc_t *, int, lun_id_t);
|
|
|
|
static __inline void rls_lun_statep(ispsoftc_t *, tstate_t *);
|
|
|
|
static __inline atio_private_data_t *isp_get_atpd(ispsoftc_t *, int);
|
2000-01-03 23:55:30 +00:00
|
|
|
static cam_status
|
2006-04-21 18:30:01 +00:00
|
|
|
create_lun_state(ispsoftc_t *, int, struct cam_path *, tstate_t **);
|
|
|
|
static void destroy_lun_state(ispsoftc_t *, tstate_t *);
|
|
|
|
static int isp_en_lun(ispsoftc_t *, union ccb *);
|
|
|
|
static void isp_ledone(ispsoftc_t *, lun_entry_t *);
|
|
|
|
static cam_status isp_abort_tgt_ccb(ispsoftc_t *, union ccb *);
|
2000-07-18 06:58:28 +00:00
|
|
|
static timeout_t isp_refire_putback_atio;
|
2001-04-04 21:58:29 +00:00
|
|
|
static void isp_complete_ctio(union ccb *);
|
|
|
|
static void isp_target_putback_atio(union ccb *);
|
2006-04-21 18:30:01 +00:00
|
|
|
static void isp_target_start_ctio(ispsoftc_t *, union ccb *);
|
|
|
|
static int isp_handle_platform_atio(ispsoftc_t *, at_entry_t *);
|
|
|
|
static int isp_handle_platform_atio2(ispsoftc_t *, at2_entry_t *);
|
|
|
|
static int isp_handle_platform_ctio(ispsoftc_t *, void *);
|
|
|
|
static int isp_handle_platform_notify_scsi(ispsoftc_t *, in_entry_t *);
|
|
|
|
static int isp_handle_platform_notify_fc(ispsoftc_t *, in_fcentry_t *);
|
2000-01-03 23:55:30 +00:00
|
|
|
|
2006-02-02 21:31:34 +00:00
|
|
|
static __inline int
|
2006-04-21 18:30:01 +00:00
|
|
|
is_lun_enabled(ispsoftc_t *isp, int bus, lun_id_t lun)
|
2000-01-03 23:55:30 +00:00
|
|
|
{
|
|
|
|
tstate_t *tptr;
|
2001-04-04 21:58:29 +00:00
|
|
|
tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(isp, bus, lun)];
|
|
|
|
if (tptr == NULL) {
|
2000-01-03 23:55:30 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
do {
|
2001-04-04 21:58:29 +00:00
|
|
|
if (tptr->lun == (lun_id_t) lun && tptr->bus == bus) {
|
2000-01-03 23:55:30 +00:00
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
} while ((tptr = tptr->next) != NULL);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2006-02-02 21:31:34 +00:00
|
|
|
static __inline int
|
2006-04-21 18:30:01 +00:00
|
|
|
are_any_luns_enabled(ispsoftc_t *isp, int port)
|
2000-01-03 23:55:30 +00:00
|
|
|
{
|
2001-04-04 21:58:29 +00:00
|
|
|
int lo, hi;
|
|
|
|
if (IS_DUALBUS(isp)) {
|
|
|
|
lo = (port * (LUN_HASH_SIZE >> 1));
|
|
|
|
hi = lo + (LUN_HASH_SIZE >> 1);
|
|
|
|
} else {
|
|
|
|
lo = 0;
|
|
|
|
hi = LUN_HASH_SIZE;
|
|
|
|
}
|
|
|
|
for (lo = 0; lo < hi; lo++) {
|
|
|
|
if (isp->isp_osinfo.lun_hash[lo]) {
|
2000-01-03 23:55:30 +00:00
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2006-02-02 21:31:34 +00:00
|
|
|
static __inline tstate_t *
|
2006-04-21 18:30:01 +00:00
|
|
|
get_lun_statep(ispsoftc_t *isp, int bus, lun_id_t lun)
|
2000-01-03 23:55:30 +00:00
|
|
|
{
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
tstate_t *tptr = NULL;
|
2000-01-03 23:55:30 +00:00
|
|
|
|
|
|
|
if (lun == CAM_LUN_WILDCARD) {
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
if (isp->isp_osinfo.tmflags[bus] & TM_WILDCARD_ENABLED) {
|
2001-08-31 21:39:04 +00:00
|
|
|
tptr = &isp->isp_osinfo.tsdflt[bus];
|
|
|
|
tptr->hold++;
|
|
|
|
return (tptr);
|
|
|
|
}
|
2004-02-08 19:17:56 +00:00
|
|
|
return (NULL);
|
2000-01-03 23:55:30 +00:00
|
|
|
} else {
|
2001-04-04 21:58:29 +00:00
|
|
|
tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(isp, bus, lun)];
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
if (tptr == NULL) {
|
|
|
|
return (NULL);
|
|
|
|
}
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
2001-04-04 21:58:29 +00:00
|
|
|
if (tptr->lun == lun && tptr->bus == bus) {
|
2000-01-03 23:55:30 +00:00
|
|
|
tptr->hold++;
|
|
|
|
return (tptr);
|
|
|
|
}
|
|
|
|
} while ((tptr = tptr->next) != NULL);
|
|
|
|
return (tptr);
|
|
|
|
}
|
|
|
|
|
2006-02-02 21:31:34 +00:00
|
|
|
static __inline void
|
2006-04-21 18:30:01 +00:00
|
|
|
rls_lun_statep(ispsoftc_t *isp, tstate_t *tptr)
|
2000-01-03 23:55:30 +00:00
|
|
|
{
|
|
|
|
if (tptr->hold)
|
|
|
|
tptr->hold--;
|
|
|
|
}
|
|
|
|
|
2006-02-02 21:31:34 +00:00
|
|
|
static __inline atio_private_data_t *
|
2006-04-21 18:30:01 +00:00
|
|
|
isp_get_atpd(ispsoftc_t *isp, int tag)
|
2001-10-01 03:48:42 +00:00
|
|
|
{
|
|
|
|
atio_private_data_t *atp;
|
|
|
|
for (atp = isp->isp_osinfo.atpdp;
|
|
|
|
atp < &isp->isp_osinfo.atpdp[ATPDPSIZE]; atp++) {
|
|
|
|
if (atp->tag == tag)
|
|
|
|
return (atp);
|
|
|
|
}
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
2000-01-03 23:55:30 +00:00
|
|
|
static cam_status
|
2006-04-21 18:30:01 +00:00
|
|
|
create_lun_state(ispsoftc_t *isp, int bus,
|
2001-04-04 21:58:29 +00:00
|
|
|
struct cam_path *path, tstate_t **rslt)
|
2000-01-03 23:55:30 +00:00
|
|
|
{
|
|
|
|
cam_status status;
|
|
|
|
lun_id_t lun;
|
2001-04-04 21:58:29 +00:00
|
|
|
int hfx;
|
2000-01-03 23:55:30 +00:00
|
|
|
tstate_t *tptr, *new;
|
|
|
|
|
|
|
|
lun = xpt_path_lun_id(path);
|
2007-07-10 07:55:59 +00:00
|
|
|
if (lun >= ISP_MAX_LUNS(isp)) {
|
2000-01-03 23:55:30 +00:00
|
|
|
return (CAM_LUN_INVALID);
|
|
|
|
}
|
2001-04-04 21:58:29 +00:00
|
|
|
if (is_lun_enabled(isp, bus, lun)) {
|
2000-01-03 23:55:30 +00:00
|
|
|
return (CAM_LUN_ALRDY_ENA);
|
|
|
|
}
|
2000-12-03 20:46:54 +00:00
|
|
|
new = (tstate_t *) malloc(sizeof (tstate_t), M_DEVBUF, M_NOWAIT|M_ZERO);
|
2000-01-03 23:55:30 +00:00
|
|
|
if (new == NULL) {
|
|
|
|
return (CAM_RESRC_UNAVAIL);
|
|
|
|
}
|
|
|
|
|
|
|
|
status = xpt_create_path(&new->owner, NULL, xpt_path_path_id(path),
|
|
|
|
xpt_path_target_id(path), xpt_path_lun_id(path));
|
|
|
|
if (status != CAM_REQ_CMP) {
|
|
|
|
free(new, M_DEVBUF);
|
|
|
|
return (status);
|
|
|
|
}
|
2001-04-04 21:58:29 +00:00
|
|
|
new->bus = bus;
|
2000-01-03 23:55:30 +00:00
|
|
|
new->lun = lun;
|
|
|
|
SLIST_INIT(&new->atios);
|
|
|
|
SLIST_INIT(&new->inots);
|
|
|
|
new->hold = 1;
|
|
|
|
|
2001-04-04 21:58:29 +00:00
|
|
|
hfx = LUN_HASH_FUNC(isp, new->bus, new->lun);
|
|
|
|
tptr = isp->isp_osinfo.lun_hash[hfx];
|
|
|
|
if (tptr == NULL) {
|
|
|
|
isp->isp_osinfo.lun_hash[hfx] = new;
|
2000-01-03 23:55:30 +00:00
|
|
|
} else {
|
|
|
|
while (tptr->next)
|
|
|
|
tptr = tptr->next;
|
|
|
|
tptr->next = new;
|
|
|
|
}
|
|
|
|
*rslt = new;
|
|
|
|
return (CAM_REQ_CMP);
|
|
|
|
}
|
|
|
|
|
2006-02-02 21:31:34 +00:00
|
|
|
static __inline void
|
2006-04-21 18:30:01 +00:00
|
|
|
destroy_lun_state(ispsoftc_t *isp, tstate_t *tptr)
|
2000-01-03 23:55:30 +00:00
|
|
|
{
|
2001-04-04 21:58:29 +00:00
|
|
|
int hfx;
|
2000-01-03 23:55:30 +00:00
|
|
|
tstate_t *lw, *pw;
|
|
|
|
|
|
|
|
if (tptr->hold) {
|
|
|
|
return;
|
|
|
|
}
|
2004-02-08 19:17:56 +00:00
|
|
|
hfx = LUN_HASH_FUNC(isp, tptr->bus, tptr->lun);
|
2001-04-04 21:58:29 +00:00
|
|
|
pw = isp->isp_osinfo.lun_hash[hfx];
|
2000-01-03 23:55:30 +00:00
|
|
|
if (pw == NULL) {
|
|
|
|
return;
|
2001-04-04 21:58:29 +00:00
|
|
|
} else if (pw->lun == tptr->lun && pw->bus == tptr->bus) {
|
|
|
|
isp->isp_osinfo.lun_hash[hfx] = pw->next;
|
2000-01-03 23:55:30 +00:00
|
|
|
} else {
|
|
|
|
lw = pw;
|
|
|
|
pw = lw->next;
|
|
|
|
while (pw) {
|
2001-04-04 21:58:29 +00:00
|
|
|
if (pw->lun == tptr->lun && pw->bus == tptr->bus) {
|
2000-01-03 23:55:30 +00:00
|
|
|
lw->next = pw->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
lw = pw;
|
|
|
|
pw = pw->next;
|
|
|
|
}
|
|
|
|
if (pw == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(tptr, M_DEVBUF);
|
1998-09-15 08:42:56 +00:00
|
|
|
}
|
|
|
|
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
/*
|
2004-02-08 19:17:56 +00:00
|
|
|
* Enable luns.
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
*/
|
2004-02-08 19:17:56 +00:00
|
|
|
static int
|
2006-04-21 18:30:01 +00:00
|
|
|
isp_en_lun(ispsoftc_t *isp, union ccb *ccb)
|
2000-01-03 23:55:30 +00:00
|
|
|
{
|
|
|
|
struct ccb_en_lun *cel = &ccb->cel;
|
2007-06-08 01:39:04 +00:00
|
|
|
tstate_t *tptr = NULL;
|
2006-02-15 00:31:48 +00:00
|
|
|
uint32_t seq;
|
2004-02-07 03:47:33 +00:00
|
|
|
int bus, cmd, av, wildcard, tm_on;
|
2000-01-03 23:55:30 +00:00
|
|
|
lun_id_t lun;
|
|
|
|
target_id_t tgt;
|
|
|
|
|
2004-02-08 19:17:56 +00:00
|
|
|
bus = XS_CHANNEL(ccb);
|
|
|
|
if (bus > 1) {
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path, "illegal bus %d\n", bus);
|
2004-02-08 19:17:56 +00:00
|
|
|
ccb->ccb_h.status = CAM_PATH_INVALID;
|
|
|
|
return (-1);
|
|
|
|
}
|
2000-01-03 23:55:30 +00:00
|
|
|
tgt = ccb->ccb_h.target_id;
|
|
|
|
lun = ccb->ccb_h.target_lun;
|
|
|
|
|
2006-12-05 07:50:23 +00:00
|
|
|
if (isp->isp_dblev & ISP_LOGTDEBUG0) {
|
|
|
|
xpt_print(ccb->ccb_h.path, "%sabling lun 0x%x on channel %d\n",
|
|
|
|
cel->enable? "en" : "dis", lun, bus);
|
|
|
|
}
|
2000-08-27 23:38:44 +00:00
|
|
|
|
2001-02-11 03:47:39 +00:00
|
|
|
if ((lun != CAM_LUN_WILDCARD) &&
|
2007-07-10 07:55:59 +00:00
|
|
|
(lun >= (lun_id_t) isp->isp_maxluns)) {
|
2000-08-27 23:38:44 +00:00
|
|
|
ccb->ccb_h.status = CAM_LUN_INVALID;
|
2004-02-08 19:17:56 +00:00
|
|
|
return (-1);
|
2000-08-27 23:38:44 +00:00
|
|
|
}
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
|
2000-08-27 23:38:44 +00:00
|
|
|
if (IS_SCSI(isp)) {
|
2001-04-04 21:58:29 +00:00
|
|
|
sdparam *sdp = isp->isp_param;
|
|
|
|
sdp += bus;
|
2000-08-27 23:38:44 +00:00
|
|
|
if (tgt != CAM_TARGET_WILDCARD &&
|
2001-04-04 21:58:29 +00:00
|
|
|
tgt != sdp->isp_initiator_id) {
|
2000-08-27 23:38:44 +00:00
|
|
|
ccb->ccb_h.status = CAM_TID_INVALID;
|
2004-02-08 19:17:56 +00:00
|
|
|
return (-1);
|
2000-08-27 23:38:44 +00:00
|
|
|
}
|
|
|
|
} else {
|
2004-02-07 03:47:33 +00:00
|
|
|
/*
|
|
|
|
* There's really no point in doing this yet w/o multi-tid
|
|
|
|
* capability. Even then, it's problematic.
|
|
|
|
*/
|
|
|
|
#if 0
|
2000-08-27 23:38:44 +00:00
|
|
|
if (tgt != CAM_TARGET_WILDCARD &&
|
2001-02-11 03:47:39 +00:00
|
|
|
tgt != FCPARAM(isp)->isp_iid) {
|
2000-08-27 23:38:44 +00:00
|
|
|
ccb->ccb_h.status = CAM_TID_INVALID;
|
2004-02-08 19:17:56 +00:00
|
|
|
return (-1);
|
2000-08-27 23:38:44 +00:00
|
|
|
}
|
2004-02-07 03:47:33 +00:00
|
|
|
#endif
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
/*
|
|
|
|
* This is as a good a place as any to check f/w capabilities.
|
|
|
|
*/
|
2006-11-02 03:21:32 +00:00
|
|
|
if (FCPARAM(isp)->isp_tmode == 0) {
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path,
|
|
|
|
"firmware does not support target mode\n");
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
|
2004-02-08 19:17:56 +00:00
|
|
|
return (-1);
|
2001-02-11 03:47:39 +00:00
|
|
|
}
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
/*
|
|
|
|
* XXX: We *could* handle non-SCCLUN f/w, but we'd have to
|
2006-12-05 07:50:23 +00:00
|
|
|
* XXX: dork with our already fragile enable/disable code.
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
*/
|
2006-11-02 03:21:32 +00:00
|
|
|
if (FCPARAM(isp)->isp_sccfw == 0) {
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path,
|
|
|
|
"firmware not SCCLUN capable\n");
|
2004-02-07 03:47:33 +00:00
|
|
|
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
|
2004-02-08 19:17:56 +00:00
|
|
|
return (-1);
|
2000-08-27 23:38:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
if (tgt == CAM_TARGET_WILDCARD) {
|
|
|
|
if (lun == CAM_LUN_WILDCARD) {
|
|
|
|
wildcard = 1;
|
|
|
|
} else {
|
|
|
|
ccb->ccb_h.status = CAM_LUN_INVALID;
|
2004-02-08 19:17:56 +00:00
|
|
|
return (-1);
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
2001-08-31 21:39:04 +00:00
|
|
|
} else {
|
|
|
|
wildcard = 0;
|
|
|
|
}
|
2000-01-03 23:55:30 +00:00
|
|
|
|
2004-02-07 03:47:33 +00:00
|
|
|
tm_on = (isp->isp_osinfo.tmflags[bus] & TM_TMODE_ENABLED) != 0;
|
|
|
|
|
2000-01-03 23:55:30 +00:00
|
|
|
/*
|
|
|
|
* Next check to see whether this is a target/lun wildcard action.
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
*
|
|
|
|
* If so, we know that we can accept commands for luns that haven't
|
|
|
|
* been enabled yet and send them upstream. Otherwise, we have to
|
|
|
|
* handle them locally (if we see them at all).
|
2000-01-03 23:55:30 +00:00
|
|
|
*/
|
2001-08-31 21:39:04 +00:00
|
|
|
|
|
|
|
if (wildcard) {
|
2001-04-04 21:58:29 +00:00
|
|
|
tptr = &isp->isp_osinfo.tsdflt[bus];
|
2000-01-03 23:55:30 +00:00
|
|
|
if (cel->enable) {
|
2004-02-08 19:17:56 +00:00
|
|
|
if (tm_on) {
|
2000-01-03 23:55:30 +00:00
|
|
|
ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
|
2004-02-08 19:17:56 +00:00
|
|
|
return (-1);
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
|
|
|
ccb->ccb_h.status =
|
|
|
|
xpt_create_path(&tptr->owner, NULL,
|
|
|
|
xpt_path_path_id(ccb->ccb_h.path),
|
|
|
|
xpt_path_target_id(ccb->ccb_h.path),
|
|
|
|
xpt_path_lun_id(ccb->ccb_h.path));
|
|
|
|
if (ccb->ccb_h.status != CAM_REQ_CMP) {
|
2004-02-08 19:17:56 +00:00
|
|
|
return (-1);
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
|
|
|
SLIST_INIT(&tptr->atios);
|
|
|
|
SLIST_INIT(&tptr->inots);
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
isp->isp_osinfo.tmflags[bus] |= TM_WILDCARD_ENABLED;
|
2000-01-03 23:55:30 +00:00
|
|
|
} else {
|
2004-02-08 19:17:56 +00:00
|
|
|
if (tm_on == 0) {
|
2001-08-31 21:39:04 +00:00
|
|
|
ccb->ccb_h.status = CAM_REQ_CMP;
|
2004-02-08 19:17:56 +00:00
|
|
|
return (-1);
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
2001-08-31 21:39:04 +00:00
|
|
|
if (tptr->hold) {
|
2000-01-03 23:55:30 +00:00
|
|
|
ccb->ccb_h.status = CAM_SCSI_BUSY;
|
2004-02-08 19:17:56 +00:00
|
|
|
return (-1);
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
2001-08-31 21:39:04 +00:00
|
|
|
xpt_free_path(tptr->owner);
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
isp->isp_osinfo.tmflags[bus] &= ~TM_WILDCARD_ENABLED;
|
2001-08-31 21:39:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now check to see whether this bus needs to be
|
|
|
|
* enabled/disabled with respect to target mode.
|
|
|
|
*/
|
|
|
|
av = bus << 31;
|
2004-02-07 03:47:33 +00:00
|
|
|
if (cel->enable && tm_on == 0) {
|
2001-08-31 21:39:04 +00:00
|
|
|
av |= ENABLE_TARGET_FLAG;
|
|
|
|
av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
|
|
|
|
if (av) {
|
|
|
|
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
|
|
|
|
if (wildcard) {
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
isp->isp_osinfo.tmflags[bus] &=
|
|
|
|
~TM_WILDCARD_ENABLED;
|
2001-08-31 21:39:04 +00:00
|
|
|
xpt_free_path(tptr->owner);
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
2004-02-08 19:17:56 +00:00
|
|
|
return (-1);
|
2001-08-31 21:39:04 +00:00
|
|
|
}
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
isp->isp_osinfo.tmflags[bus] |= TM_TMODE_ENABLED;
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path, "Target Mode Enabled\n");
|
2004-02-07 03:47:33 +00:00
|
|
|
} else if (cel->enable == 0 && tm_on && wildcard) {
|
2001-08-31 21:39:04 +00:00
|
|
|
if (are_any_luns_enabled(isp, bus)) {
|
|
|
|
ccb->ccb_h.status = CAM_SCSI_BUSY;
|
2004-02-08 19:17:56 +00:00
|
|
|
return (-1);
|
2001-08-31 21:39:04 +00:00
|
|
|
}
|
|
|
|
av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
|
|
|
|
if (av) {
|
|
|
|
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
|
2004-02-08 19:17:56 +00:00
|
|
|
return (-1);
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
isp->isp_osinfo.tmflags[bus] &= ~TM_TMODE_ENABLED;
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path, "Target Mode Disabled\n");
|
2001-08-31 21:39:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (wildcard) {
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
ccb->ccb_h.status = CAM_REQ_CMP;
|
2004-02-08 19:17:56 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find an empty slot
|
|
|
|
*/
|
|
|
|
for (seq = 0; seq < NLEACT; seq++) {
|
|
|
|
if (isp->isp_osinfo.leact[seq] == 0) {
|
|
|
|
break;
|
|
|
|
}
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
2004-02-08 19:17:56 +00:00
|
|
|
if (seq >= NLEACT) {
|
|
|
|
ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
|
|
|
|
return (-1);
|
|
|
|
|
|
|
|
}
|
|
|
|
isp->isp_osinfo.leact[seq] = ccb;
|
2000-01-03 23:55:30 +00:00
|
|
|
|
|
|
|
if (cel->enable) {
|
|
|
|
ccb->ccb_h.status =
|
2001-04-04 21:58:29 +00:00
|
|
|
create_lun_state(isp, bus, ccb->ccb_h.path, &tptr);
|
2000-01-03 23:55:30 +00:00
|
|
|
if (ccb->ccb_h.status != CAM_REQ_CMP) {
|
2004-02-08 19:17:56 +00:00
|
|
|
isp->isp_osinfo.leact[seq] = 0;
|
|
|
|
return (-1);
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
|
|
|
} else {
|
2001-04-04 21:58:29 +00:00
|
|
|
tptr = get_lun_statep(isp, bus, lun);
|
2000-01-03 23:55:30 +00:00
|
|
|
if (tptr == NULL) {
|
|
|
|
ccb->ccb_h.status = CAM_LUN_INVALID;
|
2004-02-08 19:17:56 +00:00
|
|
|
return (-1);
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cel->enable) {
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
int c, n, ulun = lun;
|
|
|
|
|
|
|
|
cmd = RQSTYPE_ENABLE_LUN;
|
|
|
|
c = DFLT_CMND_CNT;
|
|
|
|
n = DFLT_INOT_CNT;
|
|
|
|
if (IS_FC(isp) && lun != 0) {
|
|
|
|
cmd = RQSTYPE_MODIFY_LUN;
|
|
|
|
n = 0;
|
|
|
|
/*
|
|
|
|
* For SCC firmware, we only deal with setting
|
|
|
|
* (enabling or modifying) lun 0.
|
|
|
|
*/
|
|
|
|
ulun = 0;
|
|
|
|
}
|
2004-02-08 19:17:56 +00:00
|
|
|
if (isp_lun_cmd(isp, cmd, bus, tgt, ulun, c, n, seq+1) == 0) {
|
|
|
|
rls_lun_statep(isp, tptr);
|
|
|
|
ccb->ccb_h.status = CAM_REQ_INPROG;
|
|
|
|
return (seq);
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
|
|
|
} else {
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
int c, n, ulun = lun;
|
2000-01-03 23:55:30 +00:00
|
|
|
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
cmd = -RQSTYPE_MODIFY_LUN;
|
|
|
|
c = DFLT_CMND_CNT;
|
|
|
|
n = DFLT_INOT_CNT;
|
|
|
|
if (IS_FC(isp) && lun != 0) {
|
|
|
|
n = 0;
|
|
|
|
/*
|
|
|
|
* For SCC firmware, we only deal with setting
|
|
|
|
* (enabling or modifying) lun 0.
|
|
|
|
*/
|
|
|
|
ulun = 0;
|
|
|
|
}
|
2004-02-08 19:17:56 +00:00
|
|
|
if (isp_lun_cmd(isp, cmd, bus, tgt, ulun, c, n, seq+1) == 0) {
|
|
|
|
rls_lun_statep(isp, tptr);
|
|
|
|
ccb->ccb_h.status = CAM_REQ_INPROG;
|
|
|
|
return (seq);
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
}
|
2004-02-08 19:17:56 +00:00
|
|
|
}
|
|
|
|
rls_lun_statep(isp, tptr);
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path, "isp_lun_cmd failed\n");
|
2004-02-08 19:17:56 +00:00
|
|
|
isp->isp_osinfo.leact[seq] = 0;
|
|
|
|
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
|
|
|
|
return (-1);
|
|
|
|
}
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
|
2004-02-08 19:17:56 +00:00
|
|
|
static void
|
2006-04-21 18:30:01 +00:00
|
|
|
isp_ledone(ispsoftc_t *isp, lun_entry_t *lep)
|
2004-02-08 19:17:56 +00:00
|
|
|
{
|
2007-04-02 01:04:20 +00:00
|
|
|
const char lfmt[] = "now %sabled for target mode\n";
|
2004-02-08 19:17:56 +00:00
|
|
|
union ccb *ccb;
|
2006-02-15 00:31:48 +00:00
|
|
|
uint32_t seq;
|
2004-02-08 19:17:56 +00:00
|
|
|
tstate_t *tptr;
|
|
|
|
int av;
|
|
|
|
struct ccb_en_lun *cel;
|
2000-01-03 23:55:30 +00:00
|
|
|
|
2004-02-08 19:17:56 +00:00
|
|
|
seq = lep->le_reserved - 1;
|
|
|
|
if (seq >= NLEACT) {
|
|
|
|
isp_prt(isp, ISP_LOGERR,
|
|
|
|
"seq out of range (%u) in isp_ledone", seq);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ccb = isp->isp_osinfo.leact[seq];
|
|
|
|
if (ccb == 0) {
|
|
|
|
isp_prt(isp, ISP_LOGERR,
|
|
|
|
"no ccb for seq %u in isp_ledone", seq);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cel = &ccb->cel;
|
|
|
|
tptr = get_lun_statep(isp, XS_CHANNEL(ccb), XS_LUN(ccb));
|
|
|
|
if (tptr == NULL) {
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path, "null tptr in isp_ledone\n");
|
2004-02-08 19:17:56 +00:00
|
|
|
isp->isp_osinfo.leact[seq] = 0;
|
|
|
|
return;
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
2001-08-31 21:39:04 +00:00
|
|
|
|
2004-02-08 19:17:56 +00:00
|
|
|
if (lep->le_status != LUN_OK) {
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path,
|
|
|
|
"ENABLE/MODIFY LUN returned 0x%x\n", lep->le_status);
|
2004-02-08 19:17:56 +00:00
|
|
|
err:
|
2000-01-03 23:55:30 +00:00
|
|
|
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
|
|
|
|
rls_lun_statep(isp, tptr);
|
2004-02-08 19:17:56 +00:00
|
|
|
isp->isp_osinfo.leact[seq] = 0;
|
|
|
|
xpt_done(ccb);
|
|
|
|
return;
|
2000-01-03 23:55:30 +00:00
|
|
|
} else {
|
2004-02-08 19:17:56 +00:00
|
|
|
isp_prt(isp, ISP_LOGTDEBUG0,
|
|
|
|
"isp_ledone: ENABLE/MODIFY done okay");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (cel->enable) {
|
|
|
|
ccb->ccb_h.status = CAM_REQ_CMP;
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path, lfmt, "en");
|
2000-01-03 23:55:30 +00:00
|
|
|
rls_lun_statep(isp, tptr);
|
2004-02-08 19:17:56 +00:00
|
|
|
isp->isp_osinfo.leact[seq] = 0;
|
|
|
|
xpt_done(ccb);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lep->le_header.rqs_entry_type == RQSTYPE_MODIFY_LUN) {
|
|
|
|
if (isp_lun_cmd(isp, -RQSTYPE_ENABLE_LUN, XS_CHANNEL(ccb),
|
|
|
|
XS_TGT(ccb), XS_LUN(ccb), 0, 0, seq+1)) {
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path,
|
|
|
|
"isp_ledone: isp_lun_cmd failed\n");
|
2004-02-08 19:17:56 +00:00
|
|
|
goto err;
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
2004-02-08 19:17:56 +00:00
|
|
|
rls_lun_statep(isp, tptr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path, lfmt, "dis");
|
2004-02-08 19:17:56 +00:00
|
|
|
rls_lun_statep(isp, tptr);
|
|
|
|
destroy_lun_state(isp, tptr);
|
|
|
|
ccb->ccb_h.status = CAM_REQ_CMP;
|
|
|
|
isp->isp_osinfo.leact[seq] = 0;
|
|
|
|
xpt_done(ccb);
|
|
|
|
if (are_any_luns_enabled(isp, XS_CHANNEL(ccb)) == 0) {
|
|
|
|
int bus = XS_CHANNEL(ccb);
|
|
|
|
av = bus << 31;
|
|
|
|
av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
|
|
|
|
if (av) {
|
|
|
|
isp_prt(isp, ISP_LOGWARN,
|
|
|
|
"disable target mode on channel %d failed", bus);
|
|
|
|
}
|
|
|
|
isp->isp_osinfo.tmflags[bus] &= ~TM_TMODE_ENABLED;
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-02-08 19:17:56 +00:00
|
|
|
|
2000-01-03 23:55:30 +00:00
|
|
|
static cam_status
|
2006-04-21 18:30:01 +00:00
|
|
|
isp_abort_tgt_ccb(ispsoftc_t *isp, union ccb *ccb)
|
2000-01-03 23:55:30 +00:00
|
|
|
{
|
|
|
|
tstate_t *tptr;
|
|
|
|
struct ccb_hdr_slist *lp;
|
|
|
|
struct ccb_hdr *curelm;
|
2004-02-07 03:47:33 +00:00
|
|
|
int found, *ctr;
|
2000-01-03 23:55:30 +00:00
|
|
|
union ccb *accb = ccb->cab.abort_ccb;
|
|
|
|
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path, "aborting ccb %p\n", accb);
|
2000-01-03 23:55:30 +00:00
|
|
|
if (accb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
|
2004-02-07 03:47:33 +00:00
|
|
|
int badpath = 0;
|
2000-01-03 23:55:30 +00:00
|
|
|
if (IS_FC(isp) && (accb->ccb_h.target_id !=
|
|
|
|
((fcparam *) isp->isp_param)->isp_loopid)) {
|
2004-02-07 03:47:33 +00:00
|
|
|
badpath = 1;
|
2000-01-03 23:55:30 +00:00
|
|
|
} else if (IS_SCSI(isp) && (accb->ccb_h.target_id !=
|
|
|
|
((sdparam *) isp->isp_param)->isp_initiator_id)) {
|
2004-02-07 03:47:33 +00:00
|
|
|
badpath = 1;
|
|
|
|
}
|
|
|
|
if (badpath) {
|
|
|
|
/*
|
|
|
|
* Being restrictive about target ids is really about
|
|
|
|
* making sure we're aborting for the right multi-tid
|
|
|
|
* path. This doesn't really make much sense at present.
|
|
|
|
*/
|
|
|
|
#if 0
|
2000-01-03 23:55:30 +00:00
|
|
|
return (CAM_PATH_INVALID);
|
2004-02-07 03:47:33 +00:00
|
|
|
#endif
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
|
|
|
}
|
2001-04-04 21:58:29 +00:00
|
|
|
tptr = get_lun_statep(isp, XS_CHANNEL(ccb), accb->ccb_h.target_lun);
|
2000-01-03 23:55:30 +00:00
|
|
|
if (tptr == NULL) {
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path, "can't get statep\n");
|
2000-01-03 23:55:30 +00:00
|
|
|
return (CAM_PATH_INVALID);
|
|
|
|
}
|
|
|
|
if (accb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
|
|
|
|
lp = &tptr->atios;
|
2004-02-07 03:47:33 +00:00
|
|
|
ctr = &tptr->atio_count;
|
2000-01-03 23:55:30 +00:00
|
|
|
} else if (accb->ccb_h.func_code == XPT_IMMED_NOTIFY) {
|
|
|
|
lp = &tptr->inots;
|
2004-02-07 03:47:33 +00:00
|
|
|
ctr = &tptr->inot_count;
|
2000-01-03 23:55:30 +00:00
|
|
|
} else {
|
|
|
|
rls_lun_statep(isp, tptr);
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path, "bad function code %d\n",
|
|
|
|
accb->ccb_h.func_code);
|
2000-01-03 23:55:30 +00:00
|
|
|
return (CAM_UA_ABORT);
|
|
|
|
}
|
|
|
|
curelm = SLIST_FIRST(lp);
|
|
|
|
found = 0;
|
|
|
|
if (curelm == &accb->ccb_h) {
|
|
|
|
found = 1;
|
|
|
|
SLIST_REMOVE_HEAD(lp, sim_links.sle);
|
|
|
|
} else {
|
|
|
|
while(curelm != NULL) {
|
|
|
|
struct ccb_hdr *nextelm;
|
|
|
|
|
|
|
|
nextelm = SLIST_NEXT(curelm, sim_links.sle);
|
|
|
|
if (nextelm == &accb->ccb_h) {
|
|
|
|
found = 1;
|
|
|
|
SLIST_NEXT(curelm, sim_links.sle) =
|
|
|
|
SLIST_NEXT(nextelm, sim_links.sle);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
curelm = nextelm;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rls_lun_statep(isp, tptr);
|
|
|
|
if (found) {
|
2006-03-03 07:04:43 +00:00
|
|
|
(*ctr)--;
|
2000-01-03 23:55:30 +00:00
|
|
|
accb->ccb_h.status = CAM_REQ_ABORTED;
|
2004-02-07 03:47:33 +00:00
|
|
|
xpt_done(accb);
|
2000-01-03 23:55:30 +00:00
|
|
|
return (CAM_REQ_CMP);
|
|
|
|
}
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path, "ccb %p not found\n", accb);
|
2004-02-07 03:47:33 +00:00
|
|
|
return (CAM_PATH_INVALID);
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
|
|
|
|
2006-04-21 18:30:01 +00:00
|
|
|
static void
|
|
|
|
isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
|
2000-01-03 23:55:30 +00:00
|
|
|
{
|
|
|
|
void *qe;
|
2000-01-15 01:50:48 +00:00
|
|
|
struct ccb_scsiio *cso = &ccb->csio;
|
2006-11-02 03:21:32 +00:00
|
|
|
uint32_t nxti, optr, handle;
|
2006-02-15 00:31:48 +00:00
|
|
|
uint8_t local[QENTRY_LEN];
|
2000-01-03 23:55:30 +00:00
|
|
|
|
2000-07-18 06:58:28 +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
|
|
|
if (isp_getrqentry(isp, &nxti, &optr, &qe)) {
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path,
|
|
|
|
"Request Queue Overflow in isp_target_start_ctio\n");
|
2006-04-21 18:30:01 +00:00
|
|
|
XS_SETERR(ccb, CAM_REQUEUE_REQ);
|
|
|
|
goto out;
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
2006-05-22 06:49:49 +00:00
|
|
|
memset(local, 0, QENTRY_LEN);
|
2000-01-03 23:55:30 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We're either moving data or completing a command here.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (IS_FC(isp)) {
|
2001-10-01 03:48:42 +00:00
|
|
|
atio_private_data_t *atp;
|
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
|
|
|
ct2_entry_t *cto = (ct2_entry_t *) local;
|
2000-01-15 01:50:48 +00:00
|
|
|
|
2000-01-03 23:55:30 +00:00
|
|
|
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
|
|
|
|
cto->ct_header.rqs_entry_count = 1;
|
2006-11-02 03:21:32 +00:00
|
|
|
if (FCPARAM(isp)->isp_2klogin) {
|
2006-05-22 06:49:49 +00:00
|
|
|
((ct2e_entry_t *)cto)->ct_iid = cso->init_id;
|
|
|
|
} else {
|
|
|
|
cto->ct_iid = cso->init_id;
|
2006-11-02 03:21:32 +00:00
|
|
|
if (FCPARAM(isp)->isp_sccfw == 0) {
|
2006-05-22 06:49:49 +00:00
|
|
|
cto->ct_lun = ccb->ccb_h.target_lun;
|
|
|
|
}
|
2000-06-18 04:50:26 +00:00
|
|
|
}
|
2001-10-01 03:48:42 +00:00
|
|
|
|
|
|
|
atp = isp_get_atpd(isp, cso->tag_id);
|
|
|
|
if (atp == NULL) {
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path,
|
|
|
|
"cannot find private data adjunct for tag %x\n",
|
2001-10-01 03:48:42 +00:00
|
|
|
cso->tag_id);
|
2006-04-21 18:30:01 +00:00
|
|
|
XS_SETERR(ccb, CAM_REQ_CMP_ERR);
|
|
|
|
goto out;
|
2001-10-01 03:48:42 +00:00
|
|
|
}
|
2000-07-18 06:58:28 +00:00
|
|
|
|
2000-01-15 01:50:48 +00:00
|
|
|
cto->ct_rxid = cso->tag_id;
|
|
|
|
if (cso->dxfer_len == 0) {
|
|
|
|
cto->ct_flags |= CT2_FLAG_MODE1 | CT2_NO_DATA;
|
2000-07-18 06:58:28 +00:00
|
|
|
if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
|
|
|
|
cto->ct_flags |= CT2_SENDSTATUS;
|
|
|
|
cto->rsp.m1.ct_scsi_status = cso->scsi_status;
|
2001-10-01 03:48:42 +00:00
|
|
|
cto->ct_resid =
|
|
|
|
atp->orig_datalen - atp->bytes_xfered;
|
2002-06-16 05:08:02 +00:00
|
|
|
if (cto->ct_resid < 0) {
|
|
|
|
cto->rsp.m1.ct_scsi_status |=
|
|
|
|
CT2_DATA_OVER;
|
|
|
|
} else if (cto->ct_resid > 0) {
|
|
|
|
cto->rsp.m1.ct_scsi_status |=
|
|
|
|
CT2_DATA_UNDER;
|
|
|
|
}
|
2000-07-18 06:58:28 +00:00
|
|
|
}
|
2000-01-15 01:50:48 +00:00
|
|
|
if ((ccb->ccb_h.flags & CAM_SEND_SENSE) != 0) {
|
|
|
|
int m = min(cso->sense_len, MAXRESPLEN);
|
2006-05-22 06:49:49 +00:00
|
|
|
memcpy(cto->rsp.m1.ct_resp,
|
|
|
|
&cso->sense_data, m);
|
2000-01-15 01:50:48 +00:00
|
|
|
cto->rsp.m1.ct_senselen = m;
|
|
|
|
cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cto->ct_flags |= CT2_FLAG_MODE0;
|
|
|
|
if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
|
|
|
|
cto->ct_flags |= CT2_DATA_IN;
|
|
|
|
} else {
|
|
|
|
cto->ct_flags |= CT2_DATA_OUT;
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
2002-06-16 05:08:02 +00:00
|
|
|
cto->ct_reloff = atp->bytes_xfered;
|
2000-01-15 01:50:48 +00:00
|
|
|
if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
|
|
|
|
cto->ct_flags |= CT2_SENDSTATUS;
|
|
|
|
cto->rsp.m0.ct_scsi_status = cso->scsi_status;
|
2001-10-01 03:48:42 +00:00
|
|
|
cto->ct_resid =
|
|
|
|
atp->orig_datalen -
|
|
|
|
(atp->bytes_xfered + cso->dxfer_len);
|
2002-06-16 05:08:02 +00:00
|
|
|
if (cto->ct_resid < 0) {
|
|
|
|
cto->rsp.m0.ct_scsi_status |=
|
|
|
|
CT2_DATA_OVER;
|
|
|
|
} else if (cto->ct_resid > 0) {
|
|
|
|
cto->rsp.m0.ct_scsi_status |=
|
|
|
|
CT2_DATA_UNDER;
|
|
|
|
}
|
2001-10-01 03:48:42 +00:00
|
|
|
} else {
|
|
|
|
atp->last_xframt = cso->dxfer_len;
|
2000-01-04 03:45:49 +00:00
|
|
|
}
|
2000-07-18 06:58:28 +00:00
|
|
|
/*
|
|
|
|
* If we're sending data and status back together,
|
|
|
|
* we can't also send back sense data as well.
|
|
|
|
*/
|
2000-01-15 01:50:48 +00:00
|
|
|
ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
|
|
|
|
}
|
2001-10-01 03:48:42 +00:00
|
|
|
|
2001-03-21 00:46:44 +00:00
|
|
|
if (cto->ct_flags & CT2_SENDSTATUS) {
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
isp_prt(isp, ISP_LOGTDEBUG0,
|
2001-10-01 03:48:42 +00:00
|
|
|
"CTIO2[%x] STATUS %x origd %u curd %u resid %u",
|
|
|
|
cto->ct_rxid, cso->scsi_status, atp->orig_datalen,
|
|
|
|
cso->dxfer_len, cto->ct_resid);
|
2001-04-04 21:58:29 +00:00
|
|
|
cto->ct_flags |= CT2_CCINCR;
|
2002-06-16 05:08:02 +00:00
|
|
|
atp->state = ATPD_STATE_LAST_CTIO;
|
2006-04-21 18:30:01 +00:00
|
|
|
} else {
|
2002-06-16 05:08:02 +00:00
|
|
|
atp->state = ATPD_STATE_CTIO;
|
2006-04-21 18:30:01 +00:00
|
|
|
}
|
2001-04-04 21:58:29 +00:00
|
|
|
cto->ct_timeout = 10;
|
2000-01-03 23:55:30 +00:00
|
|
|
} else {
|
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
|
|
|
ct_entry_t *cto = (ct_entry_t *) local;
|
2000-01-15 01:50:48 +00:00
|
|
|
|
2000-01-03 23:55:30 +00:00
|
|
|
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
|
|
|
|
cto->ct_header.rqs_entry_count = 1;
|
2000-01-15 01:50:48 +00:00
|
|
|
cto->ct_iid = cso->init_id;
|
2001-04-04 21:58:29 +00:00
|
|
|
cto->ct_iid |= XS_CHANNEL(ccb) << 7;
|
2000-01-03 23:55:30 +00:00
|
|
|
cto->ct_tgt = ccb->ccb_h.target_id;
|
|
|
|
cto->ct_lun = ccb->ccb_h.target_lun;
|
2001-04-04 21:58:29 +00:00
|
|
|
cto->ct_fwhandle = AT_GET_HANDLE(cso->tag_id);
|
|
|
|
if (AT_HAS_TAG(cso->tag_id)) {
|
2006-02-15 00:31:48 +00:00
|
|
|
cto->ct_tag_val = (uint8_t) AT_GET_TAG(cso->tag_id);
|
2000-07-18 06:58:28 +00:00
|
|
|
cto->ct_flags |= CT_TQAE;
|
|
|
|
}
|
|
|
|
if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) {
|
|
|
|
cto->ct_flags |= CT_NODISC;
|
|
|
|
}
|
|
|
|
if (cso->dxfer_len == 0) {
|
2000-01-03 23:55:30 +00:00
|
|
|
cto->ct_flags |= CT_NO_DATA;
|
2000-01-15 01:50:48 +00:00
|
|
|
} else if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
|
|
|
|
cto->ct_flags |= CT_DATA_IN;
|
|
|
|
} else {
|
|
|
|
cto->ct_flags |= CT_DATA_OUT;
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
2000-07-18 06:58:28 +00:00
|
|
|
if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
|
2001-10-01 03:48:42 +00:00
|
|
|
cto->ct_flags |= CT_SENDSTATUS|CT_CCINCR;
|
2000-01-15 01:50:48 +00:00
|
|
|
cto->ct_scsi_status = cso->scsi_status;
|
|
|
|
cto->ct_resid = cso->resid;
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
isp_prt(isp, ISP_LOGTDEBUG0,
|
2001-04-04 21:58:29 +00:00
|
|
|
"CTIO[%x] SCSI STATUS 0x%x resid %d tag_id %x",
|
|
|
|
cto->ct_fwhandle, cso->scsi_status, cso->resid,
|
|
|
|
cso->tag_id);
|
2000-01-04 03:45:49 +00:00
|
|
|
}
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
|
2001-04-04 21:58:29 +00:00
|
|
|
cto->ct_timeout = 10;
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
|
|
|
|
2006-11-02 03:21:32 +00:00
|
|
|
if (isp_save_xs_tgt(isp, ccb, &handle)) {
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path,
|
|
|
|
"No XFLIST pointers for isp_target_start_ctio\n");
|
2006-04-21 18:30:01 +00:00
|
|
|
XS_SETERR(ccb, CAM_REQUEUE_REQ);
|
|
|
|
goto out;
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Call the dma setup routines for this entry (and any subsequent
|
|
|
|
* CTIOs) if there's data to move, and then tell the f/w it's got
|
2000-08-01 06:31:44 +00:00
|
|
|
* new things to play with. As with isp_start's usage of DMA setup,
|
2000-01-03 23:55:30 +00:00
|
|
|
* any swizzling is done in the machine dependent layer. Because
|
|
|
|
* of this, we put the request onto the queue area first in native
|
|
|
|
* format.
|
|
|
|
*/
|
|
|
|
|
2006-11-02 03:21:32 +00:00
|
|
|
if (IS_FC(isp)) {
|
|
|
|
ct2_entry_t *cto = (ct2_entry_t *) local;
|
|
|
|
cto->ct_syshandle = handle;
|
|
|
|
} else {
|
|
|
|
ct_entry_t *cto = (ct_entry_t *) local;
|
|
|
|
cto->ct_syshandle = handle;
|
|
|
|
}
|
2001-04-04 21:58:29 +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
|
|
|
switch (ISP_DMASETUP(isp, cso, (ispreq_t *) local, &nxti, optr)) {
|
2000-01-03 23:55:30 +00:00
|
|
|
case CMD_QUEUED:
|
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_ADD_REQUEST(isp, nxti);
|
2006-04-21 18:30:01 +00:00
|
|
|
ccb->ccb_h.status |= CAM_SIM_QUEUED;
|
|
|
|
return;
|
2000-01-03 23:55:30 +00:00
|
|
|
|
|
|
|
case CMD_EAGAIN:
|
2006-04-21 18:30:01 +00:00
|
|
|
XS_SETERR(ccb, CAM_REQUEUE_REQ);
|
|
|
|
break;
|
2000-01-03 23:55:30 +00:00
|
|
|
|
|
|
|
default:
|
2006-04-21 18:30:01 +00:00
|
|
|
break;
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
2006-11-02 03:21:32 +00:00
|
|
|
isp_destroy_tgt_handle(isp, handle);
|
2006-04-21 18:30:01 +00:00
|
|
|
|
|
|
|
out:
|
|
|
|
xpt_done(ccb);
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
|
|
|
|
2001-04-04 21:58:29 +00:00
|
|
|
static void
|
|
|
|
isp_refire_putback_atio(void *arg)
|
2000-07-18 06:58:28 +00:00
|
|
|
{
|
2001-04-04 21:58:29 +00:00
|
|
|
int s = splcam();
|
|
|
|
isp_target_putback_atio(arg);
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
isp_target_putback_atio(union ccb *ccb)
|
|
|
|
{
|
2006-04-21 18:30:01 +00:00
|
|
|
ispsoftc_t *isp;
|
2001-04-04 21:58:29 +00:00
|
|
|
struct ccb_scsiio *cso;
|
2006-11-02 03:21:32 +00:00
|
|
|
uint32_t nxti, optr;
|
2001-04-04 21:58:29 +00:00
|
|
|
void *qe;
|
|
|
|
|
|
|
|
isp = XS_ISP(ccb);
|
2000-07-18 06:58:28 +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
|
|
|
if (isp_getrqentry(isp, &nxti, &optr, &qe)) {
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path,
|
|
|
|
"isp_target_putback_atio: Request Queue Overflow\n");
|
2001-04-04 21:58:29 +00:00
|
|
|
(void) timeout(isp_refire_putback_atio, ccb, 10);
|
|
|
|
return;
|
2000-07-18 06:58:28 +00:00
|
|
|
}
|
2006-05-22 06:49:49 +00:00
|
|
|
memset(qe, 0, QENTRY_LEN);
|
2001-04-04 21:58:29 +00:00
|
|
|
cso = &ccb->csio;
|
2000-07-18 06:58:28 +00:00
|
|
|
if (IS_FC(isp)) {
|
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
|
|
|
at2_entry_t local, *at = &local;
|
|
|
|
MEMZERO(at, sizeof (at2_entry_t));
|
2000-07-18 06:58:28 +00:00
|
|
|
at->at_header.rqs_entry_type = RQSTYPE_ATIO2;
|
|
|
|
at->at_header.rqs_entry_count = 1;
|
2006-11-02 03:21:32 +00:00
|
|
|
if (FCPARAM(isp)->isp_sccfw) {
|
2001-04-04 21:58:29 +00:00
|
|
|
at->at_scclun = (uint16_t) ccb->ccb_h.target_lun;
|
2000-07-18 06:58:28 +00:00
|
|
|
} else {
|
2001-04-04 21:58:29 +00:00
|
|
|
at->at_lun = (uint8_t) ccb->ccb_h.target_lun;
|
2000-07-18 06:58:28 +00:00
|
|
|
}
|
|
|
|
at->at_status = CT_OK;
|
2001-04-04 21:58:29 +00:00
|
|
|
at->at_rxid = cso->tag_id;
|
2002-06-16 05:08:02 +00:00
|
|
|
at->at_iid = cso->ccb_h.target_id;
|
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_put_atio2(isp, at, qe);
|
2000-07-18 06:58:28 +00:00
|
|
|
} else {
|
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
|
|
|
at_entry_t local, *at = &local;
|
|
|
|
MEMZERO(at, sizeof (at_entry_t));
|
2000-07-18 06:58:28 +00:00
|
|
|
at->at_header.rqs_entry_type = RQSTYPE_ATIO;
|
|
|
|
at->at_header.rqs_entry_count = 1;
|
2001-04-04 21:58:29 +00:00
|
|
|
at->at_iid = cso->init_id;
|
|
|
|
at->at_iid |= XS_CHANNEL(ccb) << 7;
|
|
|
|
at->at_tgt = cso->ccb_h.target_id;
|
|
|
|
at->at_lun = cso->ccb_h.target_lun;
|
2000-07-18 06:58:28 +00:00
|
|
|
at->at_status = CT_OK;
|
2001-04-04 21:58:29 +00:00
|
|
|
at->at_tag_val = AT_GET_TAG(cso->tag_id);
|
|
|
|
at->at_handle = AT_GET_HANDLE(cso->tag_id);
|
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_put_atio(isp, at, qe);
|
2000-07-18 06:58:28 +00:00
|
|
|
}
|
|
|
|
ISP_TDQE(isp, "isp_target_putback_atio", (int) optr, qe);
|
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_ADD_REQUEST(isp, nxti);
|
2001-04-04 21:58:29 +00:00
|
|
|
isp_complete_ctio(ccb);
|
2000-07-18 06:58:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-04-04 21:58:29 +00:00
|
|
|
isp_complete_ctio(union ccb *ccb)
|
2000-07-18 06:58:28 +00:00
|
|
|
{
|
2001-04-04 21:58:29 +00:00
|
|
|
if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
|
|
|
|
ccb->ccb_h.status |= CAM_REQ_CMP;
|
2000-07-18 06:58:28 +00:00
|
|
|
}
|
2001-04-04 21:58:29 +00:00
|
|
|
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
|
|
|
|
xpt_done(ccb);
|
2000-07-18 06:58:28 +00:00
|
|
|
}
|
|
|
|
|
2000-01-03 23:55:30 +00:00
|
|
|
/*
|
|
|
|
* Handle ATIO stuff that the generic code can't.
|
|
|
|
* This means handling CDBs.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int
|
2006-04-21 18:30:01 +00:00
|
|
|
isp_handle_platform_atio(ispsoftc_t *isp, at_entry_t *aep)
|
2000-01-03 23:55:30 +00:00
|
|
|
{
|
|
|
|
tstate_t *tptr;
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
int status, bus, iswildcard;
|
2000-01-03 23:55:30 +00:00
|
|
|
struct ccb_accept_tio *atiop;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The firmware status (except for the QLTM_SVALID bit)
|
|
|
|
* indicates why this ATIO was sent to us.
|
|
|
|
*
|
|
|
|
* If QLTM_SVALID is set, the firware has recommended Sense Data.
|
|
|
|
*
|
|
|
|
* If the DISCONNECTS DISABLED bit is set in the flags field,
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
* we're still connected on the SCSI bus.
|
2000-01-03 23:55:30 +00:00
|
|
|
*/
|
|
|
|
status = aep->at_status;
|
|
|
|
if ((status & ~QLTM_SVALID) == AT_PHASE_ERROR) {
|
|
|
|
/*
|
|
|
|
* Bus Phase Sequence error. We should have sense data
|
|
|
|
* suggested by the f/w. I'm not sure quite yet what
|
|
|
|
* to do about this for CAM.
|
|
|
|
*/
|
2001-03-01 02:14:54 +00:00
|
|
|
isp_prt(isp, ISP_LOGWARN, "PHASE ERROR");
|
2000-01-03 23:55:30 +00:00
|
|
|
isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
if ((status & ~QLTM_SVALID) != AT_CDB) {
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
isp_prt(isp, ISP_LOGWARN, "bad atio (0x%x) leaked to platform",
|
2001-03-01 02:14:54 +00:00
|
|
|
status);
|
2000-01-03 23:55:30 +00:00
|
|
|
isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
bus = GET_BUS_VAL(aep->at_iid);
|
2001-04-04 21:58:29 +00:00
|
|
|
tptr = get_lun_statep(isp, bus, aep->at_lun);
|
2000-01-03 23:55:30 +00:00
|
|
|
if (tptr == NULL) {
|
2001-04-04 21:58:29 +00:00
|
|
|
tptr = get_lun_statep(isp, bus, CAM_LUN_WILDCARD);
|
2004-02-07 03:47:33 +00:00
|
|
|
if (tptr == NULL) {
|
2006-04-21 18:46:35 +00:00
|
|
|
/*
|
|
|
|
* Because we can't autofeed sense data back with
|
|
|
|
* a command for parallel SCSI, we can't give back
|
|
|
|
* a CHECK CONDITION. We'll give back a BUSY status
|
|
|
|
* instead. This works out okay because the only
|
|
|
|
* time we should, in fact, get this, is in the
|
|
|
|
* case that somebody configured us without the
|
|
|
|
* blackhole driver, so they get what they deserve.
|
|
|
|
*/
|
|
|
|
isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
|
2004-02-07 03:47:33 +00:00
|
|
|
return (0);
|
|
|
|
}
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
iswildcard = 1;
|
|
|
|
} else {
|
|
|
|
iswildcard = 0;
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios);
|
|
|
|
if (atiop == NULL) {
|
|
|
|
/*
|
|
|
|
* Because we can't autofeed sense data back with
|
|
|
|
* a command for parallel SCSI, we can't give back
|
|
|
|
* a CHECK CONDITION. We'll give back a QUEUE FULL status
|
|
|
|
* instead. This works out okay because the only time we
|
|
|
|
* should, in fact, get this, is in the case that we've
|
|
|
|
* run out of ATIOS.
|
|
|
|
*/
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(tptr->owner,
|
|
|
|
"no ATIOS for lun %d from initiator %d on channel %d\n",
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
aep->at_lun, GET_IID_VAL(aep->at_iid), bus);
|
2000-01-03 23:55:30 +00:00
|
|
|
if (aep->at_flags & AT_TQAE)
|
|
|
|
isp_endcmd(isp, aep, SCSI_STATUS_QUEUE_FULL, 0);
|
|
|
|
else
|
|
|
|
isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
rls_lun_statep(isp, tptr);
|
2000-01-03 23:55:30 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
|
2004-02-07 03:47:33 +00:00
|
|
|
tptr->atio_count--;
|
|
|
|
isp_prt(isp, ISP_LOGTDEBUG0, "Take FREE ATIO lun %d, count now %d",
|
|
|
|
aep->at_lun, tptr->atio_count);
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
if (iswildcard) {
|
2000-01-03 23:55:30 +00:00
|
|
|
atiop->ccb_h.target_id = aep->at_tgt;
|
|
|
|
atiop->ccb_h.target_lun = aep->at_lun;
|
|
|
|
}
|
|
|
|
if (aep->at_flags & AT_NODISC) {
|
2000-07-18 06:58:28 +00:00
|
|
|
atiop->ccb_h.flags = CAM_DIS_DISCONNECT;
|
|
|
|
} else {
|
|
|
|
atiop->ccb_h.flags = 0;
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
|
|
|
|
2000-07-18 06:58:28 +00:00
|
|
|
if (status & QLTM_SVALID) {
|
|
|
|
size_t amt = imin(QLTM_SENSELEN, sizeof (atiop->sense_data));
|
|
|
|
atiop->sense_len = amt;
|
|
|
|
MEMCPY(&atiop->sense_data, aep->at_sense, amt);
|
|
|
|
} else {
|
|
|
|
atiop->sense_len = 0;
|
|
|
|
}
|
2000-01-03 23:55:30 +00:00
|
|
|
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
atiop->init_id = GET_IID_VAL(aep->at_iid);
|
2000-01-03 23:55:30 +00:00
|
|
|
atiop->cdb_len = aep->at_cdblen;
|
|
|
|
MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, aep->at_cdblen);
|
|
|
|
atiop->ccb_h.status = CAM_CDB_RECVD;
|
2001-04-04 21:58:29 +00:00
|
|
|
/*
|
|
|
|
* Construct a tag 'id' based upon tag value (which may be 0..255)
|
|
|
|
* and the handle (which we have to preserve).
|
|
|
|
*/
|
2007-01-20 04:00:21 +00:00
|
|
|
AT_MAKE_TAGID(atiop->tag_id, bus, device_get_unit(isp->isp_dev), aep);
|
2001-04-04 21:58:29 +00:00
|
|
|
if (aep->at_flags & AT_TQAE) {
|
|
|
|
atiop->tag_action = aep->at_tag_type;
|
2000-01-03 23:55:30 +00:00
|
|
|
atiop->ccb_h.status |= CAM_TAG_ACTION_VALID;
|
|
|
|
}
|
|
|
|
xpt_done((union ccb*)atiop);
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
isp_prt(isp, ISP_LOGTDEBUG0,
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
"ATIO[%x] CDB=0x%x bus %d iid%d->lun%d tag 0x%x ttype 0x%x %s",
|
|
|
|
aep->at_handle, aep->at_cdb[0] & 0xff, GET_BUS_VAL(aep->at_iid),
|
|
|
|
GET_IID_VAL(aep->at_iid), aep->at_lun, aep->at_tag_val & 0xff,
|
|
|
|
aep->at_tag_type, (aep->at_flags & AT_NODISC)?
|
|
|
|
"nondisc" : "disconnecting");
|
2000-01-03 23:55:30 +00:00
|
|
|
rls_lun_statep(isp, tptr);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-04-21 18:30:01 +00:00
|
|
|
isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep)
|
2000-01-03 23:55:30 +00:00
|
|
|
{
|
2000-01-04 03:45:49 +00:00
|
|
|
lun_id_t lun;
|
2000-01-03 23:55:30 +00:00
|
|
|
tstate_t *tptr;
|
|
|
|
struct ccb_accept_tio *atiop;
|
2001-10-01 03:48:42 +00:00
|
|
|
atio_private_data_t *atp;
|
2000-01-03 23:55:30 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The firmware status (except for the QLTM_SVALID bit)
|
|
|
|
* indicates why this ATIO was sent to us.
|
|
|
|
*
|
|
|
|
* If QLTM_SVALID is set, the firware has recommended Sense Data.
|
|
|
|
*/
|
|
|
|
if ((aep->at_status & ~QLTM_SVALID) != AT_CDB) {
|
2001-03-01 02:14:54 +00:00
|
|
|
isp_prt(isp, ISP_LOGWARN,
|
|
|
|
"bogus atio (0x%x) leaked to platform", aep->at_status);
|
2000-01-03 23:55:30 +00:00
|
|
|
isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2006-11-02 03:21:32 +00:00
|
|
|
if (FCPARAM(isp)->isp_sccfw) {
|
2000-06-18 04:50:26 +00:00
|
|
|
lun = aep->at_scclun;
|
|
|
|
} else {
|
|
|
|
lun = aep->at_lun;
|
|
|
|
}
|
2001-04-04 21:58:29 +00:00
|
|
|
tptr = get_lun_statep(isp, 0, lun);
|
2000-01-03 23:55:30 +00:00
|
|
|
if (tptr == NULL) {
|
2004-02-07 03:47:33 +00:00
|
|
|
isp_prt(isp, ISP_LOGTDEBUG0,
|
|
|
|
"[0x%x] no state pointer for lun %d", aep->at_rxid, lun);
|
2001-04-04 21:58:29 +00:00
|
|
|
tptr = get_lun_statep(isp, 0, CAM_LUN_WILDCARD);
|
2004-02-07 03:47:33 +00:00
|
|
|
if (tptr == NULL) {
|
|
|
|
isp_endcmd(isp, aep,
|
|
|
|
SCSI_STATUS_CHECK_COND | ECMD_SVALID |
|
|
|
|
(0x5 << 12) | (0x25 << 16), 0);
|
|
|
|
return (0);
|
|
|
|
}
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
|
|
|
|
2001-10-01 03:48:42 +00:00
|
|
|
atp = isp_get_atpd(isp, 0);
|
2000-01-03 23:55:30 +00:00
|
|
|
atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios);
|
2001-10-01 03:48:42 +00:00
|
|
|
if (atiop == NULL || atp == NULL) {
|
2004-02-07 03:47:33 +00:00
|
|
|
|
2000-01-03 23:55:30 +00:00
|
|
|
/*
|
|
|
|
* Because we can't autofeed sense data back with
|
|
|
|
* a command for parallel SCSI, we can't give back
|
|
|
|
* a CHECK CONDITION. We'll give back a QUEUE FULL status
|
|
|
|
* instead. This works out okay because the only time we
|
|
|
|
* should, in fact, get this, is in the case that we've
|
|
|
|
* run out of ATIOS.
|
|
|
|
*/
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(tptr->owner,
|
|
|
|
"no %s for lun %d from initiator %d\n",
|
2002-06-16 05:08:02 +00:00
|
|
|
(atp == NULL && atiop == NULL)? "ATIO2s *or* ATPS" :
|
|
|
|
((atp == NULL)? "ATPs" : "ATIO2s"), lun, aep->at_iid);
|
2000-01-03 23:55:30 +00:00
|
|
|
rls_lun_statep(isp, tptr);
|
2002-06-16 05:08:02 +00:00
|
|
|
isp_endcmd(isp, aep, SCSI_STATUS_QUEUE_FULL, 0);
|
2000-01-03 23:55:30 +00:00
|
|
|
return (0);
|
|
|
|
}
|
2002-06-16 05:08:02 +00:00
|
|
|
atp->state = ATPD_STATE_ATIO;
|
2000-01-03 23:55:30 +00:00
|
|
|
SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
|
2002-06-16 05:08:02 +00:00
|
|
|
tptr->atio_count--;
|
2004-02-07 03:47:33 +00:00
|
|
|
isp_prt(isp, ISP_LOGTDEBUG0, "Take FREE ATIO lun %d, count now %d",
|
2002-06-16 05:08:02 +00:00
|
|
|
lun, tptr->atio_count);
|
2000-07-18 06:58:28 +00:00
|
|
|
|
2001-04-04 21:58:29 +00:00
|
|
|
if (tptr == &isp->isp_osinfo.tsdflt[0]) {
|
2006-11-02 03:21:32 +00:00
|
|
|
atiop->ccb_h.target_id = FCPARAM(isp)->isp_loopid;
|
2000-01-04 03:45:49 +00:00
|
|
|
atiop->ccb_h.target_lun = lun;
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
2001-02-27 00:14:39 +00:00
|
|
|
/*
|
|
|
|
* We don't get 'suggested' sense data as we do with SCSI cards.
|
|
|
|
*/
|
|
|
|
atiop->sense_len = 0;
|
2000-07-18 06:58:28 +00:00
|
|
|
|
2000-01-03 23:55:30 +00:00
|
|
|
atiop->init_id = aep->at_iid;
|
|
|
|
atiop->cdb_len = ATIO2_CDBLEN;
|
|
|
|
MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, ATIO2_CDBLEN);
|
|
|
|
atiop->ccb_h.status = CAM_CDB_RECVD;
|
|
|
|
atiop->tag_id = aep->at_rxid;
|
|
|
|
switch (aep->at_taskflags & ATIO2_TC_ATTR_MASK) {
|
|
|
|
case ATIO2_TC_ATTR_SIMPLEQ:
|
|
|
|
atiop->tag_action = MSG_SIMPLE_Q_TAG;
|
|
|
|
break;
|
|
|
|
case ATIO2_TC_ATTR_HEADOFQ:
|
|
|
|
atiop->tag_action = MSG_HEAD_OF_Q_TAG;
|
|
|
|
break;
|
|
|
|
case ATIO2_TC_ATTR_ORDERED:
|
|
|
|
atiop->tag_action = MSG_ORDERED_Q_TAG;
|
|
|
|
break;
|
|
|
|
case ATIO2_TC_ATTR_ACAQ: /* ?? */
|
|
|
|
case ATIO2_TC_ATTR_UNTAGGED:
|
|
|
|
default:
|
|
|
|
atiop->tag_action = 0;
|
|
|
|
break;
|
|
|
|
}
|
2002-06-16 05:08:02 +00:00
|
|
|
atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
|
2000-07-18 06:58:28 +00:00
|
|
|
|
2001-10-01 03:48:42 +00:00
|
|
|
atp->tag = atiop->tag_id;
|
2002-06-16 05:08:02 +00:00
|
|
|
atp->lun = lun;
|
2001-10-01 03:48:42 +00:00
|
|
|
atp->orig_datalen = aep->at_datalen;
|
|
|
|
atp->last_xframt = 0;
|
|
|
|
atp->bytes_xfered = 0;
|
2002-06-16 05:08:02 +00:00
|
|
|
atp->state = ATPD_STATE_CAM;
|
2000-01-03 23:55:30 +00:00
|
|
|
xpt_done((union ccb*)atiop);
|
2002-06-16 05:08:02 +00:00
|
|
|
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
isp_prt(isp, ISP_LOGTDEBUG0,
|
2001-03-02 06:28:55 +00:00
|
|
|
"ATIO2[%x] CDB=0x%x iid%d->lun%d tattr 0x%x datalen %u",
|
|
|
|
aep->at_rxid, aep->at_cdb[0] & 0xff, aep->at_iid,
|
2000-08-01 06:31:44 +00:00
|
|
|
lun, aep->at_taskflags, aep->at_datalen);
|
2000-01-03 23:55:30 +00:00
|
|
|
rls_lun_statep(isp, tptr);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-04-21 18:30:01 +00:00
|
|
|
isp_handle_platform_ctio(ispsoftc_t *isp, void *arg)
|
2000-01-03 23:55:30 +00:00
|
|
|
{
|
|
|
|
union ccb *ccb;
|
2001-04-04 21:58:29 +00:00
|
|
|
int sentstatus, ok, notify_cam, resid = 0;
|
2006-02-15 00:31:48 +00:00
|
|
|
uint16_t tval;
|
2000-01-03 23:55:30 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* CTIO and CTIO2 are close enough....
|
|
|
|
*/
|
|
|
|
|
2004-05-24 07:02:25 +00:00
|
|
|
ccb = isp_find_xs_tgt(isp, ((ct_entry_t *)arg)->ct_syshandle);
|
2000-01-03 23:55:30 +00:00
|
|
|
KASSERT((ccb != NULL), ("null ccb in isp_handle_platform_ctio"));
|
2004-05-24 07:02:25 +00:00
|
|
|
isp_destroy_tgt_handle(isp, ((ct_entry_t *)arg)->ct_syshandle);
|
2000-01-03 23:55:30 +00:00
|
|
|
|
|
|
|
if (IS_FC(isp)) {
|
|
|
|
ct2_entry_t *ct = arg;
|
2002-06-16 05:08:02 +00:00
|
|
|
atio_private_data_t *atp = isp_get_atpd(isp, ct->ct_rxid);
|
|
|
|
if (atp == NULL) {
|
|
|
|
isp_prt(isp, ISP_LOGERR,
|
|
|
|
"cannot find adjunct for %x after I/O",
|
|
|
|
ct->ct_rxid);
|
|
|
|
return (0);
|
|
|
|
}
|
2000-01-03 23:55:30 +00:00
|
|
|
sentstatus = ct->ct_flags & CT2_SENDSTATUS;
|
|
|
|
ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK;
|
2001-04-04 21:58:29 +00:00
|
|
|
if (ok && sentstatus && (ccb->ccb_h.flags & CAM_SEND_SENSE)) {
|
2000-01-15 01:50:48 +00:00
|
|
|
ccb->ccb_h.status |= CAM_SENT_SENSE;
|
|
|
|
}
|
2001-04-04 21:58:29 +00:00
|
|
|
notify_cam = ct->ct_header.rqs_seqno & 0x1;
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) {
|
2001-04-04 21:58:29 +00:00
|
|
|
resid = ct->ct_resid;
|
2001-10-01 03:48:42 +00:00
|
|
|
atp->bytes_xfered += (atp->last_xframt - resid);
|
|
|
|
atp->last_xframt = 0;
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
}
|
2002-06-16 05:08:02 +00:00
|
|
|
if (sentstatus || !ok) {
|
|
|
|
atp->tag = 0;
|
|
|
|
}
|
|
|
|
isp_prt(isp, ok? ISP_LOGTDEBUG0 : ISP_LOGWARN,
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
"CTIO2[%x] sts 0x%x flg 0x%x sns %d resid %d %s",
|
|
|
|
ct->ct_rxid, ct->ct_status, ct->ct_flags,
|
|
|
|
(ccb->ccb_h.status & CAM_SENT_SENSE) != 0,
|
|
|
|
resid, sentstatus? "FIN" : "MID");
|
|
|
|
tval = ct->ct_rxid;
|
2002-06-16 05:08:02 +00:00
|
|
|
|
|
|
|
/* XXX: should really come after isp_complete_ctio */
|
|
|
|
atp->state = ATPD_STATE_PDON;
|
2000-01-03 23:55:30 +00:00
|
|
|
} else {
|
|
|
|
ct_entry_t *ct = arg;
|
|
|
|
sentstatus = ct->ct_flags & CT_SENDSTATUS;
|
|
|
|
ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK;
|
2001-04-04 21:58:29 +00:00
|
|
|
/*
|
|
|
|
* We *ought* to be able to get back to the original ATIO
|
|
|
|
* here, but for some reason this gets lost. It's just as
|
|
|
|
* well because it's squirrelled away as part of periph
|
|
|
|
* private data.
|
|
|
|
*
|
|
|
|
* We can live without it as long as we continue to use
|
|
|
|
* the auto-replenish feature for CTIOs.
|
|
|
|
*/
|
|
|
|
notify_cam = ct->ct_header.rqs_seqno & 0x1;
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
if (ct->ct_status & QLTM_SVALID) {
|
2001-04-04 21:58:29 +00:00
|
|
|
char *sp = (char *)ct;
|
|
|
|
sp += CTIO_SENSE_OFFSET;
|
|
|
|
ccb->csio.sense_len =
|
|
|
|
min(sizeof (ccb->csio.sense_data), QLTM_SENSELEN);
|
|
|
|
MEMCPY(&ccb->csio.sense_data, sp, ccb->csio.sense_len);
|
|
|
|
ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
|
|
|
|
}
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) {
|
2001-04-04 21:58:29 +00:00
|
|
|
resid = ct->ct_resid;
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
}
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
isp_prt(isp, ISP_LOGTDEBUG0,
|
|
|
|
"CTIO[%x] tag %x iid %d lun %d sts %x flg %x resid %d %s",
|
|
|
|
ct->ct_fwhandle, ct->ct_tag_val, ct->ct_iid, ct->ct_lun,
|
|
|
|
ct->ct_status, ct->ct_flags, resid,
|
|
|
|
sentstatus? "FIN" : "MID");
|
|
|
|
tval = ct->ct_fwhandle;
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
2001-04-04 21:58:29 +00:00
|
|
|
ccb->csio.resid += resid;
|
2000-01-03 23:55:30 +00:00
|
|
|
|
|
|
|
/*
|
2001-04-04 21:58:29 +00:00
|
|
|
* We're here either because intermediate data transfers are done
|
|
|
|
* and/or the final status CTIO (which may have joined with a
|
|
|
|
* Data Transfer) is done.
|
2000-01-03 23:55:30 +00:00
|
|
|
*
|
|
|
|
* In any case, for this platform, the upper layers figure out
|
|
|
|
* what to do next, so all we do here is collect status and
|
2001-04-04 21:58:29 +00:00
|
|
|
* pass information along. Any DMA handles have already been
|
|
|
|
* freed.
|
2000-01-03 23:55:30 +00:00
|
|
|
*/
|
2000-07-18 06:58:28 +00:00
|
|
|
if (notify_cam == 0) {
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
isp_prt(isp, ISP_LOGTDEBUG0, " INTER CTIO[0x%x] done", tval);
|
2000-07-18 06:58:28 +00:00
|
|
|
return (0);
|
|
|
|
}
|
2001-04-04 21:58:29 +00:00
|
|
|
|
2001-10-01 03:48:42 +00:00
|
|
|
isp_prt(isp, ISP_LOGTDEBUG0, "%s CTIO[0x%x] done",
|
|
|
|
(sentstatus)? " FINAL " : "MIDTERM ", tval);
|
2001-04-04 21:58:29 +00:00
|
|
|
|
|
|
|
if (!ok) {
|
|
|
|
isp_target_putback_atio(ccb);
|
2000-07-18 06:58:28 +00:00
|
|
|
} else {
|
2001-04-04 21:58:29 +00:00
|
|
|
isp_complete_ctio(ccb);
|
2000-01-03 23:55:30 +00:00
|
|
|
|
|
|
|
}
|
2001-04-04 21:58:29 +00:00
|
|
|
return (0);
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
2002-06-16 05:08:02 +00:00
|
|
|
|
|
|
|
static int
|
2006-04-21 18:30:01 +00:00
|
|
|
isp_handle_platform_notify_scsi(ispsoftc_t *isp, in_entry_t *inp)
|
2002-06-16 05:08:02 +00:00
|
|
|
{
|
|
|
|
return (0); /* XXXX */
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-04-21 18:30:01 +00:00
|
|
|
isp_handle_platform_notify_fc(ispsoftc_t *isp, in_fcentry_t *inp)
|
2002-06-16 05:08:02 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
switch (inp->in_status) {
|
|
|
|
case IN_PORT_LOGOUT:
|
|
|
|
isp_prt(isp, ISP_LOGWARN, "port logout of iid %d",
|
|
|
|
inp->in_iid);
|
|
|
|
break;
|
|
|
|
case IN_PORT_CHANGED:
|
|
|
|
isp_prt(isp, ISP_LOGWARN, "port changed for iid %d",
|
|
|
|
inp->in_iid);
|
|
|
|
break;
|
|
|
|
case IN_GLOBAL_LOGO:
|
|
|
|
isp_prt(isp, ISP_LOGINFO, "all ports logged out");
|
|
|
|
break;
|
|
|
|
case IN_ABORT_TASK:
|
|
|
|
{
|
|
|
|
atio_private_data_t *atp = isp_get_atpd(isp, inp->in_seqid);
|
|
|
|
struct ccb_immed_notify *inot = NULL;
|
|
|
|
|
|
|
|
if (atp) {
|
|
|
|
tstate_t *tptr = get_lun_statep(isp, 0, atp->lun);
|
|
|
|
if (tptr) {
|
|
|
|
inot = (struct ccb_immed_notify *)
|
|
|
|
SLIST_FIRST(&tptr->inots);
|
|
|
|
if (inot) {
|
2004-02-07 03:47:33 +00:00
|
|
|
tptr->inot_count--;
|
2002-06-16 05:08:02 +00:00
|
|
|
SLIST_REMOVE_HEAD(&tptr->inots,
|
|
|
|
sim_links.sle);
|
2004-02-07 03:47:33 +00:00
|
|
|
isp_prt(isp, ISP_LOGTDEBUG0,
|
|
|
|
"Take FREE INOT count now %d",
|
|
|
|
tptr->inot_count);
|
2002-06-16 05:08:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
isp_prt(isp, ISP_LOGWARN,
|
|
|
|
"abort task RX_ID %x IID %d state %d",
|
|
|
|
inp->in_seqid, inp->in_iid, atp->state);
|
|
|
|
} else {
|
|
|
|
isp_prt(isp, ISP_LOGWARN,
|
|
|
|
"abort task RX_ID %x from iid %d, state unknown",
|
|
|
|
inp->in_seqid, inp->in_iid);
|
|
|
|
}
|
|
|
|
if (inot) {
|
|
|
|
inot->initiator_id = inp->in_iid;
|
|
|
|
inot->sense_len = 0;
|
|
|
|
inot->message_args[0] = MSG_ABORT_TAG;
|
|
|
|
inot->message_args[1] = inp->in_seqid & 0xff;
|
|
|
|
inot->message_args[2] = (inp->in_seqid >> 8) & 0xff;
|
2006-05-30 17:43:04 +00:00
|
|
|
inot->ccb_h.status = CAM_MESSAGE_RECV;
|
2002-06-16 05:08:02 +00:00
|
|
|
xpt_done((union ccb *)inot);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
2000-01-03 23:55:30 +00:00
|
|
|
#endif
|
|
|
|
|
1998-09-15 08:42:56 +00:00
|
|
|
static void
|
2006-02-15 00:31:48 +00:00
|
|
|
isp_cam_async(void *cbarg, uint32_t code, struct cam_path *path, void *arg)
|
1998-09-15 08:42:56 +00:00
|
|
|
{
|
|
|
|
struct cam_sim *sim;
|
2006-04-21 18:30:01 +00:00
|
|
|
ispsoftc_t *isp;
|
1998-09-15 08:42:56 +00:00
|
|
|
|
|
|
|
sim = (struct cam_sim *)cbarg;
|
2006-04-21 18:30:01 +00:00
|
|
|
isp = (ispsoftc_t *) cam_sim_softc(sim);
|
1998-09-15 08:42:56 +00:00
|
|
|
switch (code) {
|
|
|
|
case AC_LOST_DEVICE:
|
1999-10-17 18:50:47 +00:00
|
|
|
if (IS_SCSI(isp)) {
|
2006-02-15 00:31:48 +00:00
|
|
|
uint16_t oflags, nflags;
|
1998-09-15 08:42:56 +00:00
|
|
|
sdparam *sdp = isp->isp_param;
|
2001-04-04 21:58:29 +00:00
|
|
|
int tgt;
|
1998-09-15 08:42:56 +00:00
|
|
|
|
1999-12-20 01:35:04 +00:00
|
|
|
tgt = xpt_path_target_id(path);
|
2002-10-10 17:29:05 +00:00
|
|
|
if (tgt >= 0) {
|
|
|
|
sdp += cam_sim_bus(sim);
|
|
|
|
nflags = sdp->isp_devparam[tgt].nvrm_flags;
|
2001-04-04 21:58:29 +00:00
|
|
|
#ifndef ISP_TARGET_MODE
|
2002-10-10 17:29:05 +00:00
|
|
|
nflags &= DPARM_SAFE_DFLT;
|
|
|
|
if (isp->isp_loaded_fw) {
|
|
|
|
nflags |= DPARM_NARROW | DPARM_ASYNC;
|
|
|
|
}
|
2001-04-04 21:58:29 +00:00
|
|
|
#else
|
2002-10-10 17:29:05 +00:00
|
|
|
nflags = DPARM_DEFAULT;
|
2001-04-04 21:58:29 +00:00
|
|
|
#endif
|
2002-10-10 17:29:05 +00:00
|
|
|
oflags = sdp->isp_devparam[tgt].goal_flags;
|
|
|
|
sdp->isp_devparam[tgt].goal_flags = nflags;
|
|
|
|
sdp->isp_devparam[tgt].dev_update = 1;
|
|
|
|
isp->isp_update |= (1 << cam_sim_bus(sim));
|
|
|
|
(void) isp_control(isp,
|
|
|
|
ISPCTL_UPDATE_PARAMS, NULL);
|
|
|
|
sdp->isp_devparam[tgt].goal_flags = oflags;
|
|
|
|
}
|
1998-09-15 08:42:56 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2001-03-01 02:14:54 +00:00
|
|
|
isp_prt(isp, ISP_LOGWARN, "isp_cam_async: Code 0x%x", code);
|
1998-09-15 08:42:56 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-12-28 19:22:27 +00:00
|
|
|
isp_poll(struct cam_sim *sim)
|
1998-09-15 08:42:56 +00:00
|
|
|
{
|
2006-04-21 18:30:01 +00:00
|
|
|
ispsoftc_t *isp = cam_sim_softc(sim);
|
2006-11-02 03:21:32 +00:00
|
|
|
uint32_t isr;
|
|
|
|
uint16_t sema, mbox;
|
2001-08-31 21:39:04 +00:00
|
|
|
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
|
2001-08-31 21:39:04 +00:00
|
|
|
isp_intr(isp, isr, sema, mbox);
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
}
|
1998-09-15 08:42:56 +00:00
|
|
|
}
|
|
|
|
|
1999-10-17 18:50:47 +00:00
|
|
|
|
2006-11-14 08:45:48 +00:00
|
|
|
static int isp_watchdog_work(ispsoftc_t *, XS_T *);
|
|
|
|
|
|
|
|
static int
|
|
|
|
isp_watchdog_work(ispsoftc_t *isp, XS_T *xs)
|
2000-05-09 01:08:21 +00:00
|
|
|
{
|
2006-02-15 00:31:48 +00:00
|
|
|
uint32_t handle;
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
|
2000-05-09 01:08:21 +00:00
|
|
|
/*
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
* We've decided this command is dead. Make sure we're not trying
|
|
|
|
* to kill a command that's already dead by getting it's handle and
|
|
|
|
* and seeing whether it's still alive.
|
2000-05-09 01:08:21 +00:00
|
|
|
*/
|
|
|
|
handle = isp_find_handle(isp, xs);
|
|
|
|
if (handle) {
|
2006-11-02 03:21:32 +00:00
|
|
|
uint32_t isr;
|
|
|
|
uint16_t sema, mbox;
|
2001-08-31 21:39:04 +00:00
|
|
|
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
if (XS_CMD_DONE_P(xs)) {
|
2000-08-01 06:31:44 +00:00
|
|
|
isp_prt(isp, ISP_LOGDEBUG1,
|
|
|
|
"watchdog found done cmd (handle 0x%x)", handle);
|
2006-11-14 08:45:48 +00:00
|
|
|
return (1);;
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (XS_CMD_WDOG_P(xs)) {
|
2000-08-01 06:31:44 +00:00
|
|
|
isp_prt(isp, ISP_LOGDEBUG2,
|
|
|
|
"recursive watchdog (handle 0x%x)", handle);
|
2006-11-14 08:45:48 +00:00
|
|
|
return (1);
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
XS_CMD_S_WDOG(xs);
|
2001-08-31 21:39:04 +00:00
|
|
|
if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
|
|
|
|
isp_intr(isp, isr, sema, mbox);
|
|
|
|
}
|
|
|
|
if (XS_CMD_DONE_P(xs)) {
|
2000-08-01 06:31:44 +00:00
|
|
|
isp_prt(isp, ISP_LOGDEBUG2,
|
2001-08-31 21:39:04 +00:00
|
|
|
"watchdog cleanup for handle 0x%x", handle);
|
2007-05-05 20:17:23 +00:00
|
|
|
isp_free_pcmd(isp, (union ccb *)xs);
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
xpt_done((union ccb *) xs);
|
|
|
|
} else if (XS_CMD_GRACE_P(xs)) {
|
2000-07-05 06:44:17 +00:00
|
|
|
/*
|
|
|
|
* Make sure the command is *really* dead before we
|
|
|
|
* release the handle (and DMA resources) for reuse.
|
|
|
|
*/
|
2006-11-14 08:45:48 +00:00
|
|
|
(void) isp_control(isp, ISPCTL_ABORT_CMD, xs);
|
2000-07-05 06:44:17 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* After this point, the comamnd is really dead.
|
|
|
|
*/
|
2000-07-04 01:05:43 +00:00
|
|
|
if (XS_XFRLEN(xs)) {
|
|
|
|
ISP_DMAFREE(isp, xs, handle);
|
|
|
|
}
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
isp_destroy_handle(isp, handle);
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(xs->ccb_h.path,
|
|
|
|
"watchdog timeout for handle 0x%x\n", handle);
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
XS_SETERR(xs, CAM_CMD_TIMEOUT);
|
|
|
|
XS_CMD_C_WDOG(xs);
|
|
|
|
isp_done(xs);
|
|
|
|
} else {
|
|
|
|
XS_CMD_C_WDOG(xs);
|
|
|
|
xs->ccb_h.timeout_ch = timeout(isp_watchdog, xs, hz);
|
|
|
|
XS_CMD_S_GRACE(xs);
|
2006-11-02 03:21:32 +00:00
|
|
|
isp->isp_sendmarker |= 1 << XS_CHANNEL(xs);
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
}
|
2006-11-14 08:45:48 +00:00
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
isp_watchdog(void *arg)
|
|
|
|
{
|
|
|
|
ispsoftc_t *isp;
|
|
|
|
XS_T *xs = arg;
|
2007-05-05 20:17:23 +00:00
|
|
|
int r;
|
|
|
|
|
|
|
|
for (r = 0, isp = isplist; r && isp; isp = isp->isp_osinfo.next) {
|
|
|
|
ISP_LOCK(isp);
|
|
|
|
r = isp_watchdog_work(isp, xs);
|
|
|
|
ISP_UNLOCK(isp);
|
2006-11-14 08:45:48 +00:00
|
|
|
}
|
|
|
|
if (isp == NULL) {
|
|
|
|
printf("isp_watchdog: nobody had %p active\n", arg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-12 04:54:30 +00:00
|
|
|
#if __FreeBSD_version >= 600000
|
2006-11-14 08:45:48 +00:00
|
|
|
static void
|
2007-02-23 05:51:57 +00:00
|
|
|
isp_make_here(ispsoftc_t *isp, int tgt)
|
2006-11-14 08:45:48 +00:00
|
|
|
{
|
2007-02-23 05:51:57 +00:00
|
|
|
union ccb *ccb;
|
|
|
|
/*
|
|
|
|
* Allocate a CCB, create a wildcard path for this bus,
|
|
|
|
* and schedule a rescan.
|
|
|
|
*/
|
2007-04-18 04:58:53 +00:00
|
|
|
ccb = xpt_alloc_ccb_nowait();
|
2007-02-23 05:51:57 +00:00
|
|
|
if (ccb == NULL) {
|
|
|
|
isp_prt(isp, ISP_LOGWARN, "unable to alloc CCB for rescan");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
|
|
|
|
cam_sim_path(isp->isp_sim), tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
|
|
|
isp_prt(isp, ISP_LOGWARN, "unable to create path for rescan");
|
|
|
|
xpt_free_ccb(ccb);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
xpt_rescan(ccb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
isp_make_gone(ispsoftc_t *isp, int tgt)
|
|
|
|
{
|
|
|
|
struct cam_path *tp;
|
|
|
|
if (xpt_create_path(&tp, NULL, cam_sim_path(isp->isp_sim), tgt,
|
2006-11-14 08:45:48 +00:00
|
|
|
CAM_LUN_WILDCARD) == CAM_REQ_CMP) {
|
2007-02-23 05:51:57 +00:00
|
|
|
xpt_async(AC_LOST_DEVICE, tp, NULL);
|
|
|
|
xpt_free_path(tp);
|
2006-11-14 08:45:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#define isp_make_here(isp, tgt) do { ; } while (0)
|
|
|
|
#define isp_make_gone(isp, tgt) do { ; } while (0)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Gone Device Timer Function- when we have decided that a device has gone
|
|
|
|
* away, we wait a specific period of time prior to telling the OS it has
|
|
|
|
* gone away.
|
|
|
|
*
|
|
|
|
* This timer function fires once a second and then scans the port database
|
|
|
|
* for devices that are marked dead but still have a virtual target assigned.
|
|
|
|
* We decrement a counter for that port database entry, and when it hits zero,
|
|
|
|
* we tell the OS the device has gone away.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
isp_gdt(void *arg)
|
|
|
|
{
|
|
|
|
ispsoftc_t *isp = arg;
|
|
|
|
fcportdb_t *lp;
|
|
|
|
int dbidx, tgt, more_to_do = 0;
|
|
|
|
|
|
|
|
ISP_LOCK(isp);
|
2007-05-05 20:17:23 +00:00
|
|
|
isp_prt(isp, ISP_LOGDEBUG0, "GDT timer expired");
|
2006-11-14 08:45:48 +00:00
|
|
|
for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
|
|
|
|
lp = &FCPARAM(isp)->portdb[dbidx];
|
|
|
|
|
|
|
|
if (lp->state != FC_PORTDB_STATE_ZOMBIE) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (lp->ini_map_idx == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (lp->new_reserved == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
lp->new_reserved -= 1;
|
|
|
|
if (lp->new_reserved != 0) {
|
|
|
|
more_to_do++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
tgt = lp->ini_map_idx - 1;
|
|
|
|
FCPARAM(isp)->isp_ini_map[tgt] = 0;
|
|
|
|
lp->ini_map_idx = 0;
|
|
|
|
lp->state = FC_PORTDB_STATE_NIL;
|
|
|
|
isp_prt(isp, ISP_LOGCONFIG, prom3, lp->portid, tgt,
|
|
|
|
"Gone Device Timeout");
|
|
|
|
isp_make_gone(isp, tgt);
|
|
|
|
}
|
|
|
|
if (more_to_do) {
|
2007-05-05 20:17:23 +00:00
|
|
|
isp->isp_osinfo.gdt_running = 1;
|
|
|
|
callout_reset(&isp->isp_osinfo.gdt, hz, isp_gdt, isp);
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
} else {
|
2006-11-14 08:45:48 +00:00
|
|
|
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
|
|
|
|
"stopping Gone Device Timer");
|
|
|
|
isp->isp_osinfo.gdt_running = 0;
|
2000-05-09 01:08:21 +00:00
|
|
|
}
|
2000-07-04 01:05:43 +00:00
|
|
|
ISP_UNLOCK(isp);
|
2000-05-09 01:08:21 +00:00
|
|
|
}
|
|
|
|
|
2006-11-14 08:45:48 +00:00
|
|
|
/*
|
|
|
|
* Loop Down Timer Function- when loop goes down, a timer is started and
|
|
|
|
* and after it expires we come here and take all probational devices that
|
|
|
|
* the OS knows about and the tell the OS that they've gone away.
|
|
|
|
*
|
|
|
|
* We don't clear the devices out of our port database because, when loop
|
|
|
|
* come back up, we have to do some actual cleanup with the chip at that
|
|
|
|
* point (implicit PLOGO, e.g., to get the chip's port database state right).
|
|
|
|
*/
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
static void
|
2006-11-14 08:45:48 +00:00
|
|
|
isp_ldt(void *arg)
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
{
|
2006-04-21 18:30:01 +00:00
|
|
|
ispsoftc_t *isp = arg;
|
2006-11-14 08:45:48 +00:00
|
|
|
fcportdb_t *lp;
|
|
|
|
int dbidx, tgt;
|
|
|
|
|
|
|
|
ISP_LOCK(isp);
|
|
|
|
|
2007-05-05 20:17:23 +00:00
|
|
|
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Loop Down Timer expired");
|
|
|
|
|
2006-11-14 08:45:48 +00:00
|
|
|
/*
|
|
|
|
* Notify to the OS all targets who we now consider have departed.
|
|
|
|
*/
|
|
|
|
for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
|
|
|
|
lp = &FCPARAM(isp)->portdb[dbidx];
|
|
|
|
|
|
|
|
if (lp->state != FC_PORTDB_STATE_PROBATIONAL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (lp->ini_map_idx == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX: CLEAN UP AND COMPLETE ANY PENDING COMMANDS FIRST!
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Mark that we've announced that this device is gone....
|
|
|
|
*/
|
|
|
|
lp->reserved = 1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* but *don't* change the state of the entry. Just clear
|
|
|
|
* any target id stuff and announce to CAM that the
|
|
|
|
* device is gone. This way any necessary PLOGO stuff
|
|
|
|
* will happen when loop comes back up.
|
|
|
|
*/
|
2006-04-21 18:30:01 +00:00
|
|
|
|
2006-11-14 08:45:48 +00:00
|
|
|
tgt = lp->ini_map_idx - 1;
|
|
|
|
FCPARAM(isp)->isp_ini_map[tgt] = 0;
|
|
|
|
lp->ini_map_idx = 0;
|
|
|
|
isp_prt(isp, ISP_LOGCONFIG, prom3, lp->portid, tgt,
|
|
|
|
"Loop Down Timeout");
|
|
|
|
isp_make_gone(isp, tgt);
|
|
|
|
}
|
2006-04-21 18:30:01 +00:00
|
|
|
|
2006-11-14 08:45:48 +00:00
|
|
|
/*
|
|
|
|
* The loop down timer has expired. Wake up the kthread
|
|
|
|
* to notice that fact (or make it false).
|
|
|
|
*/
|
|
|
|
isp->isp_osinfo.loop_down_time = isp->isp_osinfo.loop_down_limit+1;
|
2007-05-05 20:17:23 +00:00
|
|
|
wakeup(ISP_KT_WCHAN(isp));
|
2006-11-14 08:45:48 +00:00
|
|
|
ISP_UNLOCK(isp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
isp_kthread(void *arg)
|
|
|
|
{
|
|
|
|
ispsoftc_t *isp = arg;
|
|
|
|
int slp = 0;
|
2006-04-21 18:30:01 +00:00
|
|
|
#if __FreeBSD_version < 500000
|
2007-05-05 20:17:23 +00:00
|
|
|
int s = splcam();
|
|
|
|
#elif __FreeBSD_version < 700037
|
2002-09-06 18:20:59 +00:00
|
|
|
mtx_lock(&Giant);
|
2007-05-05 20:17:23 +00:00
|
|
|
#else
|
|
|
|
mtx_lock(&isp->isp_osinfo.lock);
|
2002-09-03 04:31:55 +00:00
|
|
|
#endif
|
2002-07-08 17:42:47 +00:00
|
|
|
/*
|
|
|
|
* The first loop is for our usage where we have yet to have
|
|
|
|
* gotten good fibre channel state.
|
|
|
|
*/
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
for (;;) {
|
2006-11-14 08:45:48 +00:00
|
|
|
int wasfrozen, lb, lim;
|
2002-07-08 17:42:47 +00:00
|
|
|
|
2006-11-14 08:45:48 +00:00
|
|
|
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
|
|
|
|
"isp_kthread: checking FC state");
|
|
|
|
isp->isp_osinfo.mbox_sleep_ok = 1;
|
2006-11-02 03:21:32 +00:00
|
|
|
lb = isp_fc_runstate(isp, 250000);
|
2006-11-14 08:45:48 +00:00
|
|
|
isp->isp_osinfo.mbox_sleep_ok = 0;
|
2006-11-02 03:21:32 +00:00
|
|
|
if (lb) {
|
2006-11-14 08:45:48 +00:00
|
|
|
/*
|
|
|
|
* Increment loop down time by the last sleep interval
|
|
|
|
*/
|
|
|
|
isp->isp_osinfo.loop_down_time += slp;
|
2006-11-02 03:21:32 +00:00
|
|
|
|
|
|
|
if (lb < 0) {
|
2006-11-14 08:45:48 +00:00
|
|
|
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
|
2006-11-02 03:21:32 +00:00
|
|
|
"kthread: FC loop not up (down count %d)",
|
|
|
|
isp->isp_osinfo.loop_down_time);
|
|
|
|
} else {
|
2006-11-14 08:45:48 +00:00
|
|
|
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
|
2006-11-02 03:21:32 +00:00
|
|
|
"kthread: FC got to %d (down count %d)",
|
|
|
|
lb, isp->isp_osinfo.loop_down_time);
|
2001-07-25 04:23:52 +00:00
|
|
|
}
|
2006-11-02 03:21:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we've never seen loop up and we've waited longer
|
2006-11-14 08:45:48 +00:00
|
|
|
* than quickboot time, or we've seen loop up but we've
|
|
|
|
* waited longer than loop_down_limit, give up and go
|
|
|
|
* to sleep until loop comes up.
|
2006-11-02 03:21:32 +00:00
|
|
|
*/
|
2006-11-14 08:45:48 +00:00
|
|
|
if (FCPARAM(isp)->loop_seen_once == 0) {
|
|
|
|
lim = isp_quickboot_time;
|
2006-11-02 03:21:32 +00:00
|
|
|
} else {
|
2006-11-14 08:45:48 +00:00
|
|
|
lim = isp->isp_osinfo.loop_down_limit;
|
2006-11-02 03:21:32 +00:00
|
|
|
}
|
2006-11-14 08:45:48 +00:00
|
|
|
if (isp->isp_osinfo.loop_down_time >= lim) {
|
|
|
|
isp_freeze_loopdown(isp, "loop limit hit");
|
|
|
|
slp = 0;
|
|
|
|
} else if (isp->isp_osinfo.loop_down_time < 10) {
|
|
|
|
slp = 1;
|
|
|
|
} else if (isp->isp_osinfo.loop_down_time < 30) {
|
|
|
|
slp = 5;
|
|
|
|
} else if (isp->isp_osinfo.loop_down_time < 60) {
|
|
|
|
slp = 10;
|
|
|
|
} else if (isp->isp_osinfo.loop_down_time < 120) {
|
|
|
|
slp = 20;
|
2006-11-02 03:21:32 +00:00
|
|
|
} else {
|
2006-11-14 08:45:48 +00:00
|
|
|
slp = 30;
|
2006-11-02 03:21:32 +00:00
|
|
|
}
|
2006-11-14 08:45:48 +00:00
|
|
|
|
2006-11-02 03:21:32 +00:00
|
|
|
} else {
|
2006-11-14 08:45:48 +00:00
|
|
|
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
|
|
|
|
"isp_kthread: FC state OK");
|
2006-11-02 03:21:32 +00:00
|
|
|
isp->isp_osinfo.loop_down_time = 0;
|
|
|
|
slp = 0;
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
}
|
2002-07-08 17:42:47 +00:00
|
|
|
|
2001-07-25 04:23:52 +00:00
|
|
|
/*
|
2006-11-02 03:21:32 +00:00
|
|
|
* If we'd frozen the simq, unfreeze it now so that CAM
|
|
|
|
* can start sending us commands. If the FC state isn't
|
|
|
|
* okay yet, they'll hit that in isp_start which will
|
|
|
|
* freeze the queue again.
|
2001-07-25 04:23:52 +00:00
|
|
|
*/
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN;
|
|
|
|
isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN;
|
|
|
|
if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) {
|
2006-11-14 08:45:48 +00:00
|
|
|
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
|
|
|
|
"isp_kthread: releasing simq");
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
xpt_release_simq(isp->isp_sim, 1);
|
|
|
|
}
|
2006-11-14 08:45:48 +00:00
|
|
|
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
|
|
|
|
"isp_kthread: sleep time %d", slp);
|
2007-05-05 20:17:23 +00:00
|
|
|
#if __FreeBSD_version < 700037
|
|
|
|
tsleep(ISP_KT_WCHAN(isp), PRIBIO, "ispf", slp * hz);
|
2006-04-21 18:30:01 +00:00
|
|
|
#else
|
2007-05-05 20:17:23 +00:00
|
|
|
msleep(ISP_KT_WCHAN(isp), &isp->isp_osinfo.lock,
|
|
|
|
PRIBIO, "ispf", slp * hz);
|
2002-09-03 04:31:55 +00:00
|
|
|
#endif
|
2006-11-02 03:21:32 +00:00
|
|
|
/*
|
|
|
|
* If slp is zero, we're waking up for the first time after
|
|
|
|
* things have been okay. In this case, we set a deferral state
|
|
|
|
* for all commands and delay hysteresis seconds before starting
|
|
|
|
* the FC state evaluation. This gives the loop/fabric a chance
|
|
|
|
* to settle.
|
|
|
|
*/
|
|
|
|
if (slp == 0 && isp->isp_osinfo.hysteresis) {
|
2006-11-14 08:45:48 +00:00
|
|
|
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
|
|
|
|
"isp_kthread: sleep hysteresis tick time %d",
|
|
|
|
isp->isp_osinfo.hysteresis * hz);
|
2007-05-05 20:17:23 +00:00
|
|
|
#if __FreeBSD_version < 700037
|
2006-11-02 03:21:32 +00:00
|
|
|
(void) tsleep(&isp_fabric_hysteresis, PRIBIO, "ispT",
|
|
|
|
(isp->isp_osinfo.hysteresis * hz));
|
2007-05-05 20:17:23 +00:00
|
|
|
#else
|
|
|
|
(void) msleep(&isp_fabric_hysteresis,
|
|
|
|
&isp->isp_osinfo.lock, PRIBIO, "ispT",
|
|
|
|
(isp->isp_osinfo.hysteresis * hz));
|
|
|
|
#endif
|
2006-11-02 03:21:32 +00:00
|
|
|
}
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
}
|
2007-05-05 20:17:23 +00:00
|
|
|
#if __FreeBSD_version < 500000
|
|
|
|
splx(s);
|
|
|
|
#elif __FreeBSD_version < 700037
|
|
|
|
mtx_unlock(&Giant);
|
|
|
|
#else
|
|
|
|
mtx_unlock(&isp->isp_osinfo.lock);
|
|
|
|
#endif
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
}
|
|
|
|
|
2007-05-05 20:17:23 +00:00
|
|
|
#if __FreeBSD_version < 500000
|
|
|
|
static void isp_action_wrk(struct cam_sim *, union ccb *);
|
1998-09-15 08:42:56 +00:00
|
|
|
static void
|
1998-12-28 19:22:27 +00:00
|
|
|
isp_action(struct cam_sim *sim, union ccb *ccb)
|
1998-09-15 08:42:56 +00:00
|
|
|
{
|
2007-05-05 20:17:23 +00:00
|
|
|
ispsoftc_t *isp = (ispsoftc_t *)cam_sim_softc(sim);
|
|
|
|
ISP_LOCK(isp);
|
|
|
|
isp_action_wrk(sim, ccb);
|
|
|
|
ISP_UNLOCK(isp);
|
|
|
|
}
|
|
|
|
#define isp_action isp_action_wrk
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static void
|
|
|
|
isp_action(struct cam_sim *sim, union ccb *ccb)
|
|
|
|
{
|
|
|
|
int bus, tgt, ts, error, lim;
|
2006-04-21 18:30:01 +00:00
|
|
|
ispsoftc_t *isp;
|
1998-10-15 23:46:33 +00:00
|
|
|
struct ccb_trans_settings *cts;
|
1998-09-15 08:42:56 +00:00
|
|
|
|
|
|
|
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n"));
|
|
|
|
|
2006-04-21 18:30:01 +00:00
|
|
|
isp = (ispsoftc_t *)cam_sim_softc(sim);
|
1999-08-16 20:11:45 +00:00
|
|
|
if (isp->isp_state != ISP_RUNSTATE &&
|
|
|
|
ccb->ccb_h.func_code == XPT_SCSI_IO) {
|
1999-03-17 05:04:39 +00:00
|
|
|
isp_init(isp);
|
|
|
|
if (isp->isp_state != ISP_INITSTATE) {
|
|
|
|
/*
|
|
|
|
* Lie. Say it was a selection timeout.
|
|
|
|
*/
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
ccb->ccb_h.status = CAM_SEL_TIMEOUT | CAM_DEV_QFRZN;
|
1999-08-16 20:11:45 +00:00
|
|
|
xpt_freeze_devq(ccb->ccb_h.path, 1);
|
1999-03-17 05:04:39 +00:00
|
|
|
xpt_done(ccb);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
isp->isp_state = ISP_RUNSTATE;
|
|
|
|
}
|
2000-08-01 06:31:44 +00:00
|
|
|
isp_prt(isp, ISP_LOGDEBUG2, "isp_action code %x", ccb->ccb_h.func_code);
|
2007-05-05 20:17:23 +00:00
|
|
|
ISP_PCMD(ccb) = NULL;
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
|
1998-09-15 08:42:56 +00:00
|
|
|
switch (ccb->ccb_h.func_code) {
|
|
|
|
case XPT_SCSI_IO: /* Execute the requested I/O operation */
|
|
|
|
/*
|
|
|
|
* Do a couple of preliminary checks...
|
|
|
|
*/
|
|
|
|
if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
|
|
|
|
if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) {
|
|
|
|
ccb->ccb_h.status = CAM_REQ_INVALID;
|
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1999-08-16 20:11:45 +00:00
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
if (ccb->ccb_h.target_id > (ISP_MAX_TARGETS(isp) - 1)) {
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path, "invalid target\n");
|
1999-08-16 20:11:45 +00:00
|
|
|
ccb->ccb_h.status = CAM_PATH_INVALID;
|
|
|
|
} else if (ccb->ccb_h.target_lun > (ISP_MAX_LUNS(isp) - 1)) {
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(ccb->ccb_h.path, "invalid lun\n");
|
1999-08-16 20:11:45 +00:00
|
|
|
ccb->ccb_h.status = CAM_PATH_INVALID;
|
1998-09-15 08:42:56 +00:00
|
|
|
}
|
|
|
|
if (ccb->ccb_h.status == CAM_PATH_INVALID) {
|
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
}
|
1999-08-16 20:11:45 +00:00
|
|
|
#endif
|
2007-05-05 20:17:23 +00:00
|
|
|
ccb->csio.scsi_status = SCSI_STATUS_OK;
|
|
|
|
if (isp_get_pcmd(isp, ccb)) {
|
|
|
|
isp_prt(isp, ISP_LOGWARN, "out of PCMDs");
|
|
|
|
cam_freeze_devq(ccb->ccb_h.path);
|
|
|
|
cam_release_devq(ccb->ccb_h.path,
|
|
|
|
RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0);
|
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
}
|
2000-08-01 06:31:44 +00:00
|
|
|
error = isp_start((XS_T *) ccb);
|
1999-08-16 20:11:45 +00:00
|
|
|
switch (error) {
|
1998-09-15 08:42:56 +00:00
|
|
|
case CMD_QUEUED:
|
2006-11-14 08:45:48 +00:00
|
|
|
XS_CMD_S_CLEAR(ccb);
|
1998-09-15 08:42:56 +00:00
|
|
|
ccb->ccb_h.status |= CAM_SIM_QUEUED;
|
2007-05-05 20:17:23 +00:00
|
|
|
if (ccb->ccb_h.timeout == CAM_TIME_INFINITY) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ts = ccb->ccb_h.timeout;
|
|
|
|
if (ts == CAM_TIME_DEFAULT) {
|
|
|
|
ts = 60*1000;
|
2000-05-09 01:08:21 +00:00
|
|
|
}
|
2007-05-05 20:17:23 +00:00
|
|
|
ts = isp_mstohz(ts);
|
|
|
|
callout_reset(&PISP_PCMD(ccb)->wdog, ts,
|
|
|
|
isp_watchdog, ccb);
|
1998-09-15 08:42:56 +00:00
|
|
|
break;
|
1999-08-16 20:11:45 +00:00
|
|
|
case CMD_RQLATER:
|
2006-11-02 03:21:32 +00:00
|
|
|
/*
|
2006-11-14 08:45:48 +00:00
|
|
|
* Handle initial and subsequent loop down cases
|
2006-11-02 03:21:32 +00:00
|
|
|
*/
|
2006-11-14 08:45:48 +00:00
|
|
|
if (FCPARAM(isp)->loop_seen_once == 0) {
|
|
|
|
lim = isp_quickboot_time;
|
|
|
|
} else {
|
|
|
|
lim = isp->isp_osinfo.loop_down_limit;
|
|
|
|
}
|
|
|
|
if (isp->isp_osinfo.loop_down_time >= lim) {
|
|
|
|
isp_prt(isp, ISP_LOGDEBUG0,
|
|
|
|
"%d.%d downtime (%d) > lim (%d)",
|
|
|
|
XS_TGT(ccb), XS_LUN(ccb),
|
|
|
|
isp->isp_osinfo.loop_down_time, lim);
|
|
|
|
ccb->ccb_h.status =
|
|
|
|
CAM_SEL_TIMEOUT|CAM_DEV_QFRZN;
|
|
|
|
xpt_freeze_devq(ccb->ccb_h.path, 1);
|
2007-05-05 20:17:23 +00:00
|
|
|
isp_free_pcmd(isp, ccb);
|
2001-07-25 04:23:52 +00:00
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
}
|
2006-11-14 08:45:48 +00:00
|
|
|
isp_prt(isp, ISP_LOGDEBUG0,
|
|
|
|
"%d.%d retry later", XS_TGT(ccb), XS_LUN(ccb));
|
|
|
|
/*
|
|
|
|
* Otherwise, retry in a while.
|
|
|
|
*/
|
|
|
|
cam_freeze_devq(ccb->ccb_h.path);
|
|
|
|
cam_release_devq(ccb->ccb_h.path,
|
|
|
|
RELSIM_RELEASE_AFTER_TIMEOUT, 0, 1000, 0);
|
|
|
|
XS_SETERR(ccb, CAM_REQUEUE_REQ);
|
2007-05-05 20:17:23 +00:00
|
|
|
isp_free_pcmd(isp, ccb);
|
1998-09-15 08:42:56 +00:00
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
1999-08-16 20:11:45 +00:00
|
|
|
case CMD_EAGAIN:
|
2007-05-05 20:17:23 +00:00
|
|
|
XS_SETERR(ccb, CAM_REQUEUE_REQ);
|
|
|
|
isp_free_pcmd(isp, ccb);
|
1998-09-15 08:42:56 +00:00
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
1999-08-16 20:11:45 +00:00
|
|
|
case CMD_COMPLETE:
|
|
|
|
isp_done((struct ccb_scsiio *) ccb);
|
|
|
|
break;
|
|
|
|
default:
|
2000-12-05 07:39:54 +00:00
|
|
|
isp_prt(isp, ISP_LOGERR,
|
|
|
|
"What's this? 0x%x at %d in file %s",
|
2000-12-31 20:50:56 +00:00
|
|
|
error, __LINE__, __FILE__);
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
XS_SETERR(ccb, CAM_REQ_CMP_ERR);
|
2007-05-05 20:17:23 +00:00
|
|
|
isp_free_pcmd(isp, ccb);
|
1999-08-16 20:11:45 +00:00
|
|
|
xpt_done(ccb);
|
1998-09-15 08:42:56 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2000-01-03 23:55:30 +00:00
|
|
|
#ifdef ISP_TARGET_MODE
|
1998-09-15 08:42:56 +00:00
|
|
|
case XPT_EN_LUN: /* Enable LUN as a target */
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
{
|
2006-11-02 03:21:32 +00:00
|
|
|
int seq, i;
|
2004-02-08 19:17:56 +00:00
|
|
|
seq = isp_en_lun(isp, ccb);
|
|
|
|
if (seq < 0) {
|
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
for (i = 0; isp->isp_osinfo.leact[seq] && i < 30 * 1000; i++) {
|
2006-11-02 03:21:32 +00:00
|
|
|
uint32_t isr;
|
|
|
|
uint16_t sema, mbox;
|
2004-02-08 19:17:56 +00:00
|
|
|
if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
|
|
|
|
isp_intr(isp, isr, sema, mbox);
|
|
|
|
}
|
|
|
|
DELAY(1000);
|
|
|
|
}
|
1998-09-15 08:42:56 +00:00
|
|
|
break;
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
}
|
2000-01-03 23:55:30 +00:00
|
|
|
case XPT_NOTIFY_ACK: /* recycle notify ack */
|
|
|
|
case XPT_IMMED_NOTIFY: /* Add Immediate Notify Resource */
|
|
|
|
case XPT_ACCEPT_TARGET_IO: /* Add Accept Target IO Resource */
|
|
|
|
{
|
2001-04-04 21:58:29 +00:00
|
|
|
tstate_t *tptr =
|
|
|
|
get_lun_statep(isp, XS_CHANNEL(ccb), ccb->ccb_h.target_lun);
|
2000-01-03 23:55:30 +00:00
|
|
|
if (tptr == NULL) {
|
|
|
|
ccb->ccb_h.status = CAM_LUN_INVALID;
|
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
}
|
2000-07-18 06:58:28 +00:00
|
|
|
ccb->ccb_h.sim_priv.entries[0].field = 0;
|
|
|
|
ccb->ccb_h.sim_priv.entries[1].ptr = isp;
|
2002-06-16 05:08:02 +00:00
|
|
|
ccb->ccb_h.flags = 0;
|
|
|
|
|
2000-01-03 23:55:30 +00:00
|
|
|
if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
|
2002-06-16 05:08:02 +00:00
|
|
|
/*
|
|
|
|
* Note that the command itself may not be done-
|
|
|
|
* it may not even have had the first CTIO sent.
|
|
|
|
*/
|
|
|
|
tptr->atio_count++;
|
|
|
|
isp_prt(isp, ISP_LOGTDEBUG0,
|
2004-02-07 03:47:33 +00:00
|
|
|
"Put FREE ATIO, lun %d, count now %d",
|
2002-06-16 05:08:02 +00:00
|
|
|
ccb->ccb_h.target_lun, tptr->atio_count);
|
|
|
|
SLIST_INSERT_HEAD(&tptr->atios, &ccb->ccb_h,
|
|
|
|
sim_links.sle);
|
|
|
|
} else if (ccb->ccb_h.func_code == XPT_IMMED_NOTIFY) {
|
2004-02-07 03:47:33 +00:00
|
|
|
tptr->inot_count++;
|
|
|
|
isp_prt(isp, ISP_LOGTDEBUG0,
|
|
|
|
"Put FREE INOT, lun %d, count now %d",
|
|
|
|
ccb->ccb_h.target_lun, tptr->inot_count);
|
2000-01-03 23:55:30 +00:00
|
|
|
SLIST_INSERT_HEAD(&tptr->inots, &ccb->ccb_h,
|
|
|
|
sim_links.sle);
|
2002-06-16 05:08:02 +00:00
|
|
|
} else {
|
2004-02-07 03:47:33 +00:00
|
|
|
isp_prt(isp, ISP_LOGWARN, "Got Notify ACK");;
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
|
|
|
rls_lun_statep(isp, tptr);
|
|
|
|
ccb->ccb_h.status = CAM_REQ_INPROG;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case XPT_CONT_TARGET_IO:
|
|
|
|
{
|
2006-04-21 18:30:01 +00:00
|
|
|
isp_target_start_ctio(isp, ccb);
|
2000-01-03 23:55:30 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
1998-09-15 08:42:56 +00:00
|
|
|
case XPT_RESET_DEV: /* BDR the specified SCSI device */
|
2000-01-03 23:55:30 +00:00
|
|
|
|
|
|
|
bus = cam_sim_bus(xpt_path_sim(ccb->ccb_h.path));
|
|
|
|
tgt = ccb->ccb_h.target_id;
|
|
|
|
tgt |= (bus << 16);
|
|
|
|
|
1999-05-11 05:10:06 +00:00
|
|
|
error = isp_control(isp, ISPCTL_RESET_DEV, &tgt);
|
1998-09-15 08:42:56 +00:00
|
|
|
if (error) {
|
|
|
|
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
|
|
|
|
} else {
|
|
|
|
ccb->ccb_h.status = CAM_REQ_CMP;
|
|
|
|
}
|
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
case XPT_ABORT: /* Abort the specified CCB */
|
2000-01-03 23:55:30 +00:00
|
|
|
{
|
|
|
|
union ccb *accb = ccb->cab.abort_ccb;
|
|
|
|
switch (accb->ccb_h.func_code) {
|
|
|
|
#ifdef ISP_TARGET_MODE
|
|
|
|
case XPT_ACCEPT_TARGET_IO:
|
|
|
|
case XPT_IMMED_NOTIFY:
|
|
|
|
ccb->ccb_h.status = isp_abort_tgt_ccb(isp, ccb);
|
|
|
|
break;
|
|
|
|
case XPT_CONT_TARGET_IO:
|
2000-08-01 06:31:44 +00:00
|
|
|
isp_prt(isp, ISP_LOGERR, "cannot abort CTIOs yet");
|
2000-01-03 23:55:30 +00:00
|
|
|
ccb->ccb_h.status = CAM_UA_ABORT;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case XPT_SCSI_IO:
|
|
|
|
error = isp_control(isp, ISPCTL_ABORT_CMD, ccb);
|
|
|
|
if (error) {
|
|
|
|
ccb->ccb_h.status = CAM_UA_ABORT;
|
|
|
|
} else {
|
|
|
|
ccb->ccb_h.status = CAM_REQ_CMP;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ccb->ccb_h.status = CAM_REQ_INVALID;
|
|
|
|
break;
|
1998-09-15 08:42:56 +00:00
|
|
|
}
|
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
2000-01-03 23:55:30 +00:00
|
|
|
}
|
2006-12-18 23:50:30 +00:00
|
|
|
#ifdef CAM_NEW_TRAN_CODE
|
2001-07-04 18:54:29 +00:00
|
|
|
#define IS_CURRENT_SETTINGS(c) (c->type == CTS_TYPE_CURRENT_SETTINGS)
|
2006-12-18 23:50:30 +00:00
|
|
|
#else
|
|
|
|
#define IS_CURRENT_SETTINGS(c) (c->flags & CCB_TRANS_CURRENT_SETTINGS)
|
|
|
|
#endif
|
1998-09-15 08:42:56 +00:00
|
|
|
case XPT_SET_TRAN_SETTINGS: /* Nexus Settings */
|
|
|
|
cts = &ccb->cts;
|
2001-07-30 01:00:21 +00:00
|
|
|
if (!IS_CURRENT_SETTINGS(cts)) {
|
|
|
|
ccb->ccb_h.status = CAM_REQ_INVALID;
|
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
}
|
1998-09-15 08:42:56 +00:00
|
|
|
tgt = cts->ccb_h.target_id;
|
1999-10-17 18:50:47 +00:00
|
|
|
if (IS_SCSI(isp)) {
|
2006-12-18 23:50:30 +00:00
|
|
|
#ifndef CAM_NEW_TRAN_CODE
|
|
|
|
sdparam *sdp = isp->isp_param;
|
|
|
|
uint16_t *dptr;
|
|
|
|
|
|
|
|
bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
|
|
|
|
|
|
|
|
sdp += bus;
|
|
|
|
/*
|
|
|
|
* We always update (internally) from goal_flags
|
|
|
|
* so any request to change settings just gets
|
|
|
|
* vectored to that location.
|
|
|
|
*/
|
|
|
|
dptr = &sdp->isp_devparam[tgt].goal_flags;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note that these operations affect the
|
|
|
|
* the goal flags (goal_flags)- not
|
|
|
|
* the current state flags. Then we mark
|
|
|
|
* things so that the next operation to
|
|
|
|
* this HBA will cause the update to occur.
|
|
|
|
*/
|
|
|
|
if (cts->valid & CCB_TRANS_DISC_VALID) {
|
|
|
|
if ((cts->flags & CCB_TRANS_DISC_ENB) != 0) {
|
|
|
|
*dptr |= DPARM_DISC;
|
|
|
|
} else {
|
|
|
|
*dptr &= ~DPARM_DISC;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cts->valid & CCB_TRANS_TQ_VALID) {
|
|
|
|
if ((cts->flags & CCB_TRANS_TAG_ENB) != 0) {
|
|
|
|
*dptr |= DPARM_TQING;
|
|
|
|
} else {
|
|
|
|
*dptr &= ~DPARM_TQING;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID) {
|
|
|
|
switch (cts->bus_width) {
|
|
|
|
case MSG_EXT_WDTR_BUS_16_BIT:
|
|
|
|
*dptr |= DPARM_WIDE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
*dptr &= ~DPARM_WIDE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Any SYNC RATE of nonzero and SYNC_OFFSET
|
|
|
|
* of nonzero will cause us to go to the
|
|
|
|
* selected (from NVRAM) maximum value for
|
|
|
|
* this device. At a later point, we'll
|
|
|
|
* allow finer control.
|
|
|
|
*/
|
|
|
|
if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) &&
|
|
|
|
(cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) &&
|
|
|
|
(cts->sync_offset > 0)) {
|
|
|
|
*dptr |= DPARM_SYNC;
|
|
|
|
} else {
|
|
|
|
*dptr &= ~DPARM_SYNC;
|
|
|
|
}
|
|
|
|
*dptr |= DPARM_SAFE_DFLT;
|
|
|
|
#else
|
2001-07-04 18:54:29 +00:00
|
|
|
struct ccb_trans_settings_scsi *scsi =
|
|
|
|
&cts->proto_specific.scsi;
|
|
|
|
struct ccb_trans_settings_spi *spi =
|
|
|
|
&cts->xport_specific.spi;
|
|
|
|
sdparam *sdp = isp->isp_param;
|
2006-02-15 00:31:48 +00:00
|
|
|
uint16_t *dptr;
|
2001-07-04 18:54:29 +00:00
|
|
|
|
2006-12-03 07:22:15 +00:00
|
|
|
if (spi->valid == 0 && scsi->valid == 0) {
|
|
|
|
ccb->ccb_h.status = CAM_REQ_CMP;
|
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2001-07-04 18:54:29 +00:00
|
|
|
bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
|
|
|
|
sdp += bus;
|
|
|
|
/*
|
2001-07-30 01:00:21 +00:00
|
|
|
* We always update (internally) from goal_flags
|
2001-07-04 18:54:29 +00:00
|
|
|
* so any request to change settings just gets
|
|
|
|
* vectored to that location.
|
|
|
|
*/
|
2001-07-30 01:00:21 +00:00
|
|
|
dptr = &sdp->isp_devparam[tgt].goal_flags;
|
2001-07-04 18:54:29 +00:00
|
|
|
|
|
|
|
if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
|
|
|
|
if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
|
|
|
|
*dptr |= DPARM_DISC;
|
|
|
|
else
|
|
|
|
*dptr &= ~DPARM_DISC;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
|
|
|
|
if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
|
|
|
|
*dptr |= DPARM_TQING;
|
|
|
|
else
|
|
|
|
*dptr &= ~DPARM_TQING;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
|
|
|
|
if (spi->bus_width == MSG_EXT_WDTR_BUS_16_BIT)
|
|
|
|
*dptr |= DPARM_WIDE;
|
|
|
|
else
|
|
|
|
*dptr &= ~DPARM_WIDE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX: FIX ME
|
|
|
|
*/
|
|
|
|
if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) &&
|
2001-07-30 01:00:21 +00:00
|
|
|
(spi->valid & CTS_SPI_VALID_SYNC_RATE) &&
|
|
|
|
(spi->sync_period && spi->sync_offset)) {
|
2001-07-04 18:54:29 +00:00
|
|
|
*dptr |= DPARM_SYNC;
|
2001-07-30 01:00:21 +00:00
|
|
|
/*
|
|
|
|
* XXX: CHECK FOR LEGALITY
|
|
|
|
*/
|
|
|
|
sdp->isp_devparam[tgt].goal_period =
|
|
|
|
spi->sync_period;
|
|
|
|
sdp->isp_devparam[tgt].goal_offset =
|
|
|
|
spi->sync_offset;
|
2001-07-04 18:54:29 +00:00
|
|
|
} else {
|
|
|
|
*dptr &= ~DPARM_SYNC;
|
|
|
|
}
|
2006-12-18 23:50:30 +00:00
|
|
|
#endif
|
2000-12-05 07:39:54 +00:00
|
|
|
isp_prt(isp, ISP_LOGDEBUG0,
|
2006-12-03 07:22:15 +00:00
|
|
|
"SET (%d.%d.%d) to flags %x off %x per %x",
|
|
|
|
bus, tgt, cts->ccb_h.target_lun,
|
|
|
|
sdp->isp_devparam[tgt].goal_flags,
|
2001-07-30 01:00:21 +00:00
|
|
|
sdp->isp_devparam[tgt].goal_offset,
|
|
|
|
sdp->isp_devparam[tgt].goal_period);
|
1998-09-15 08:42:56 +00:00
|
|
|
sdp->isp_devparam[tgt].dev_update = 1;
|
1999-05-11 05:10:06 +00:00
|
|
|
isp->isp_update |= (1 << bus);
|
1998-09-15 08:42:56 +00:00
|
|
|
}
|
|
|
|
ccb->ccb_h.status = CAM_REQ_CMP;
|
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
case XPT_GET_TRAN_SETTINGS:
|
|
|
|
cts = &ccb->cts;
|
|
|
|
tgt = cts->ccb_h.target_id;
|
1999-10-17 18:50:47 +00:00
|
|
|
if (IS_FC(isp)) {
|
2006-12-18 23:50:30 +00:00
|
|
|
#ifndef CAM_NEW_TRAN_CODE
|
|
|
|
/*
|
|
|
|
* a lot of normal SCSI things don't make sense.
|
|
|
|
*/
|
|
|
|
cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB;
|
|
|
|
cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
|
|
|
|
/*
|
|
|
|
* How do you measure the width of a high
|
|
|
|
* speed serial bus? Well, in bytes.
|
|
|
|
*
|
|
|
|
* Offset and period make no sense, though, so we set
|
|
|
|
* (above) a 'base' transfer speed to be gigabit.
|
|
|
|
*/
|
|
|
|
cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
|
|
|
|
#else
|
2001-07-04 18:54:29 +00:00
|
|
|
fcparam *fcp = isp->isp_param;
|
2006-12-09 01:30:05 +00:00
|
|
|
struct ccb_trans_settings_scsi *scsi =
|
|
|
|
&cts->proto_specific.scsi;
|
2001-07-04 18:54:29 +00:00
|
|
|
struct ccb_trans_settings_fc *fc =
|
|
|
|
&cts->xport_specific.fc;
|
|
|
|
|
|
|
|
cts->protocol = PROTO_SCSI;
|
|
|
|
cts->protocol_version = SCSI_REV_2;
|
|
|
|
cts->transport = XPORT_FC;
|
|
|
|
cts->transport_version = 0;
|
|
|
|
|
2006-12-09 01:30:05 +00:00
|
|
|
scsi->valid = CTS_SCSI_VALID_TQ;
|
|
|
|
scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
|
2001-07-04 18:54:29 +00:00
|
|
|
fc->valid = CTS_FC_VALID_SPEED;
|
2007-08-23 15:57:13 +00:00
|
|
|
fc->bitrate = 100000;
|
|
|
|
if (fcp->isp_gbspeed == 4 || fcp->isp_gbspeed == 2)
|
|
|
|
fc->bitrate *= fcp->isp_gbspeed;
|
2001-07-04 18:54:29 +00:00
|
|
|
if (tgt > 0 && tgt < MAX_FC_TARG) {
|
2006-11-02 03:21:32 +00:00
|
|
|
fcportdb_t *lp = &fcp->portdb[tgt];
|
2001-07-04 18:54:29 +00:00
|
|
|
fc->wwnn = lp->node_wwn;
|
|
|
|
fc->wwpn = lp->port_wwn;
|
|
|
|
fc->port = lp->portid;
|
|
|
|
fc->valid |= CTS_FC_VALID_WWNN |
|
|
|
|
CTS_FC_VALID_WWPN | CTS_FC_VALID_PORT;
|
|
|
|
}
|
2006-12-18 23:50:30 +00:00
|
|
|
#endif
|
1998-09-15 08:42:56 +00:00
|
|
|
} else {
|
2006-12-18 23:50:30 +00:00
|
|
|
#ifdef CAM_NEW_TRAN_CODE
|
2001-07-04 18:54:29 +00:00
|
|
|
struct ccb_trans_settings_scsi *scsi =
|
|
|
|
&cts->proto_specific.scsi;
|
|
|
|
struct ccb_trans_settings_spi *spi =
|
|
|
|
&cts->xport_specific.spi;
|
2006-12-18 23:50:30 +00:00
|
|
|
#endif
|
1998-09-15 08:42:56 +00:00
|
|
|
sdparam *sdp = isp->isp_param;
|
1999-05-11 05:10:06 +00:00
|
|
|
int bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
|
2006-02-15 00:31:48 +00:00
|
|
|
uint16_t dval, pval, oval;
|
1998-09-15 08:42:56 +00:00
|
|
|
|
1999-05-11 05:10:06 +00:00
|
|
|
sdp += bus;
|
2001-07-04 18:54:29 +00:00
|
|
|
|
|
|
|
if (IS_CURRENT_SETTINGS(cts)) {
|
1999-05-12 19:00:16 +00:00
|
|
|
sdp->isp_devparam[tgt].dev_refresh = 1;
|
|
|
|
isp->isp_update |= (1 << bus);
|
|
|
|
(void) isp_control(isp, ISPCTL_UPDATE_PARAMS,
|
|
|
|
NULL);
|
2001-07-30 01:00:21 +00:00
|
|
|
dval = sdp->isp_devparam[tgt].actv_flags;
|
|
|
|
oval = sdp->isp_devparam[tgt].actv_offset;
|
|
|
|
pval = sdp->isp_devparam[tgt].actv_period;
|
1999-03-25 22:52:45 +00:00
|
|
|
} else {
|
2001-07-30 01:00:21 +00:00
|
|
|
dval = sdp->isp_devparam[tgt].nvrm_flags;
|
|
|
|
oval = sdp->isp_devparam[tgt].nvrm_offset;
|
|
|
|
pval = sdp->isp_devparam[tgt].nvrm_period;
|
1999-03-25 22:52:45 +00:00
|
|
|
}
|
1998-09-15 08:42:56 +00:00
|
|
|
|
2006-12-18 23:50:30 +00:00
|
|
|
#ifndef CAM_NEW_TRAN_CODE
|
|
|
|
cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
|
|
|
|
|
|
|
|
if (dval & DPARM_DISC) {
|
|
|
|
cts->flags |= CCB_TRANS_DISC_ENB;
|
|
|
|
}
|
|
|
|
if (dval & DPARM_TQING) {
|
|
|
|
cts->flags |= CCB_TRANS_TAG_ENB;
|
|
|
|
}
|
|
|
|
if (dval & DPARM_WIDE) {
|
|
|
|
cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
|
|
|
|
} else {
|
|
|
|
cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
|
|
|
|
}
|
|
|
|
cts->valid = CCB_TRANS_BUS_WIDTH_VALID |
|
|
|
|
CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
|
|
|
|
|
|
|
|
if ((dval & DPARM_SYNC) && oval != 0) {
|
|
|
|
cts->sync_period = pval;
|
|
|
|
cts->sync_offset = oval;
|
|
|
|
cts->valid |=
|
|
|
|
CCB_TRANS_SYNC_RATE_VALID |
|
|
|
|
CCB_TRANS_SYNC_OFFSET_VALID;
|
|
|
|
}
|
|
|
|
#else
|
2001-07-04 18:54:29 +00:00
|
|
|
cts->protocol = PROTO_SCSI;
|
|
|
|
cts->protocol_version = SCSI_REV_2;
|
|
|
|
cts->transport = XPORT_SPI;
|
|
|
|
cts->transport_version = 2;
|
|
|
|
|
2006-12-03 07:22:15 +00:00
|
|
|
spi->valid = 0;
|
|
|
|
scsi->valid = 0;
|
|
|
|
spi->flags = 0;
|
|
|
|
scsi->flags = 0;
|
2001-07-04 18:54:29 +00:00
|
|
|
if (dval & DPARM_DISC) {
|
|
|
|
spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
|
|
|
|
}
|
2001-07-30 01:00:21 +00:00
|
|
|
if ((dval & DPARM_SYNC) && oval && pval) {
|
2001-07-04 18:54:29 +00:00
|
|
|
spi->sync_offset = oval;
|
|
|
|
spi->sync_period = pval;
|
2006-12-03 07:22:15 +00:00
|
|
|
} else {
|
|
|
|
spi->sync_offset = 0;
|
|
|
|
spi->sync_period = 0;
|
2001-07-04 18:54:29 +00:00
|
|
|
}
|
2006-12-03 07:22:15 +00:00
|
|
|
spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
|
|
|
|
spi->valid |= CTS_SPI_VALID_SYNC_RATE;
|
2001-07-04 18:54:29 +00:00
|
|
|
spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
|
|
|
|
if (dval & DPARM_WIDE) {
|
|
|
|
spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
|
|
|
|
} else {
|
|
|
|
spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
|
|
|
|
}
|
|
|
|
if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
|
|
|
|
scsi->valid = CTS_SCSI_VALID_TQ;
|
2006-12-03 07:22:15 +00:00
|
|
|
if (dval & DPARM_TQING) {
|
|
|
|
scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
|
|
|
|
}
|
2001-07-04 18:54:29 +00:00
|
|
|
spi->valid |= CTS_SPI_VALID_DISC;
|
|
|
|
}
|
2006-12-18 23:50:30 +00:00
|
|
|
#endif
|
2000-12-05 07:39:54 +00:00
|
|
|
isp_prt(isp, ISP_LOGDEBUG0,
|
2006-12-03 07:22:15 +00:00
|
|
|
"GET %s (%d.%d.%d) to flags %x off %x per %x",
|
2001-07-30 01:00:21 +00:00
|
|
|
IS_CURRENT_SETTINGS(cts)? "ACTIVE" : "NVRAM",
|
2006-12-03 07:22:15 +00:00
|
|
|
bus, tgt, cts->ccb_h.target_lun, dval, oval, pval);
|
1998-09-15 08:42:56 +00:00
|
|
|
}
|
|
|
|
ccb->ccb_h.status = CAM_REQ_CMP;
|
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case XPT_CALC_GEOMETRY:
|
2006-04-21 18:30:01 +00:00
|
|
|
#if __FreeBSD_version < 500000
|
1998-09-15 08:42:56 +00:00
|
|
|
{
|
|
|
|
struct ccb_calc_geometry *ccg;
|
2006-04-21 18:30:01 +00:00
|
|
|
u_int32_t secs_per_cylinder;
|
|
|
|
u_int32_t size_mb;
|
1998-09-15 08:42:56 +00:00
|
|
|
|
|
|
|
ccg = &ccb->ccg;
|
|
|
|
if (ccg->block_size == 0) {
|
|
|
|
ccb->ccb_h.status = CAM_REQ_INVALID;
|
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
}
|
2006-04-21 18:30:01 +00:00
|
|
|
size_mb = ccg->volume_size /((1024L * 1024L) / ccg->block_size);
|
|
|
|
if (size_mb > 1024) {
|
|
|
|
ccg->heads = 255;
|
|
|
|
ccg->secs_per_track = 63;
|
|
|
|
} else {
|
|
|
|
ccg->heads = 64;
|
|
|
|
ccg->secs_per_track = 32;
|
|
|
|
}
|
|
|
|
secs_per_cylinder = ccg->heads * ccg->secs_per_track;
|
|
|
|
ccg->cylinders = ccg->volume_size / secs_per_cylinder;
|
|
|
|
ccb->ccb_h.status = CAM_REQ_CMP;
|
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
{
|
|
|
|
cam_calc_geometry(&ccb->ccg, /*extended*/1);
|
1998-09-15 08:42:56 +00:00
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
}
|
2006-04-21 18:30:01 +00:00
|
|
|
#endif
|
1998-09-15 08:42:56 +00:00
|
|
|
case XPT_RESET_BUS: /* Reset the specified bus */
|
1999-10-17 18:50:47 +00:00
|
|
|
bus = cam_sim_bus(sim);
|
|
|
|
error = isp_control(isp, ISPCTL_RESET_BUS, &bus);
|
1998-09-15 08:42:56 +00:00
|
|
|
if (error)
|
|
|
|
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
|
1999-02-09 01:08:38 +00:00
|
|
|
else {
|
2007-05-05 20:17:23 +00:00
|
|
|
if (bootverbose) {
|
|
|
|
xpt_print(ccb->ccb_h.path, "reset bus\n");
|
|
|
|
}
|
1999-05-11 05:10:06 +00:00
|
|
|
if (cam_sim_bus(sim) && isp->isp_path2 != NULL)
|
|
|
|
xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
|
|
|
|
else if (isp->isp_path != NULL)
|
1999-02-09 01:08:38 +00:00
|
|
|
xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
|
1998-09-15 08:42:56 +00:00
|
|
|
ccb->ccb_h.status = CAM_REQ_CMP;
|
1999-02-09 01:08:38 +00:00
|
|
|
}
|
1998-09-15 08:42:56 +00:00
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case XPT_TERM_IO: /* Terminate the I/O process */
|
|
|
|
ccb->ccb_h.status = CAM_REQ_INVALID;
|
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case XPT_PATH_INQ: /* Path routing inquiry */
|
|
|
|
{
|
|
|
|
struct ccb_pathinq *cpi = &ccb->cpi;
|
|
|
|
|
|
|
|
cpi->version_num = 1;
|
2000-01-03 23:55:30 +00:00
|
|
|
#ifdef ISP_TARGET_MODE
|
2001-04-04 21:58:29 +00:00
|
|
|
cpi->target_sprt = PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO;
|
2000-01-03 23:55:30 +00:00
|
|
|
#else
|
1998-09-15 08:42:56 +00:00
|
|
|
cpi->target_sprt = 0;
|
2000-01-03 23:55:30 +00:00
|
|
|
#endif
|
1998-09-15 08:42:56 +00:00
|
|
|
cpi->hba_eng_cnt = 0;
|
1999-08-16 20:11:45 +00:00
|
|
|
cpi->max_target = ISP_MAX_TARGETS(isp) - 1;
|
|
|
|
cpi->max_lun = ISP_MAX_LUNS(isp) - 1;
|
|
|
|
cpi->bus_id = cam_sim_bus(sim);
|
1999-03-25 22:52:45 +00:00
|
|
|
if (IS_FC(isp)) {
|
|
|
|
cpi->hba_misc = PIM_NOBUSRESET;
|
1999-08-16 20:11:45 +00:00
|
|
|
/*
|
|
|
|
* Because our loop ID can shift from time to time,
|
|
|
|
* make our initiator ID out of range of our bus.
|
|
|
|
*/
|
|
|
|
cpi->initiator_id = cpi->max_target + 1;
|
|
|
|
|
Add a number of interrelated CAM feature enhancements and bug fixes.
NOTE: These changes will require recompilation of any userland
applications, like cdrecord, xmcd, etc., that use the CAM passthrough
interface. A make world is recommended.
camcontrol.[c8]:
- We now support two new commands, "tags" and "negotiate".
- The tags commands allows users to view the number of tagged
openings for a device as well as a number of other related
parameters, and it allows users to set tagged openings for
a device.
- The negotiate command allows users to enable and disable
disconnection and tagged queueing, set sync rates, offsets
and bus width. Note that not all of those features are
available for all controllers. Only the adv, ahc, and ncr
drivers fully support all of the features at this point.
Some cards do not allow the setting of sync rates, offsets and
the like, and some of the drivers don't have any facilities to
do so. Some drivers, like the adw driver, only support enabling
or disabling sync negotiation, but do not support setting sync
rates.
- new description in the camcontrol man page of how to format a disk
- cleanup of the camcontrol inquiry command
- add support in the 'devlist' command for skipping unconfigured devices if
-v was not specified on the command line.
- make use of the new base_transfer_speed in the path inquiry CCB.
- fix CCB bzero cases
cam_xpt.c, cam_sim.[ch], cam_ccb.h:
- new flags on many CCB function codes to designate whether they're
non-immediate, use a user-supplied CCB, and can only be passed from
userland programs via the xpt device. Use these flags in the transport
layer and pass driver to categorize CCBs.
- new flag in the transport layer device matching code for device nodes
that indicates whether a device is unconfigured
- bump the CAM version from 0x10 to 0x11
- Change the CAM ioctls to use the version as their group code, so we can
force users to recompile code even when the CCB size doesn't change.
- add + fill in a new value in the path inquiry CCB, base_transfer_speed.
Remove a corresponding field from the cam_sim structure, and add code to
every SIM to set this field to the proper value.
- Fix the set transfer settings code in the transport layer.
scsi_cd.c:
- make some variables volatile instead of just casting them in various
places
- fix a race condition in the changer code
- attach unless we get a "logical unit not supported" error. This should
fix all of the cases where people have devices that return weird errors
when they don't have media in the drive.
scsi_da.c:
- attach unless we get a "logical unit not supported" error
scsi_pass.c:
- for immediate CCBs, just malloc a CCB to send the user request in. This
gets rid of the 'held' count problem in camcontrol tags.
scsi_pass.h:
- change the CAM ioctls to use the CAM version as their group code.
adv driver:
- Allow changing the sync rate and offset separately.
adw driver
- Allow changing the sync rate and offset separately.
aha driver:
- Don't return CAM_REQ_CMP for SET_TRAN_SETTINGS CCBs.
ahc driver:
- Allow setting offset and sync rate separately
bt driver:
- Don't return CAM_REQ_CMP for SET_TRAN_SETTINGS CCBs.
NCR driver:
- Fix the ultra/ultra 2 negotiation bug
- allow setting both the sync rate and offset separately
Other HBA drivers:
- Put code in to set the base_transfer_speed field for
XPT_GET_TRAN_SETTINGS CCBs.
Reviewed by: gibbs, mjacob (isp), imp (aha)
1999-05-06 20:16:39 +00:00
|
|
|
/*
|
|
|
|
* Set base transfer capabilities for Fibre Channel.
|
|
|
|
* Technically not correct because we don't know
|
|
|
|
* what media we're running on top of- but we'll
|
|
|
|
* look good if we always say 100MB/s.
|
|
|
|
*/
|
2007-08-23 15:57:13 +00:00
|
|
|
cpi->base_transfer_speed = 100000;
|
|
|
|
if (FCPARAM(isp)->isp_gbspeed == 4 ||
|
|
|
|
FCPARAM(isp)->isp_gbspeed == 2)
|
|
|
|
cpi->base_transfer_speed *=
|
|
|
|
FCPARAM(isp)->isp_gbspeed;
|
1999-08-16 20:11:45 +00:00
|
|
|
cpi->hba_inquiry = PI_TAG_ABLE;
|
2006-12-18 23:50:30 +00:00
|
|
|
#ifdef CAM_NEW_TRAN_CODE
|
2001-07-04 18:54:29 +00:00
|
|
|
cpi->transport = XPORT_FC;
|
2006-12-18 23:50:30 +00:00
|
|
|
cpi->transport_version = 0;
|
|
|
|
#endif
|
1998-09-15 08:42:56 +00:00
|
|
|
} else {
|
1999-05-11 05:10:06 +00:00
|
|
|
sdparam *sdp = isp->isp_param;
|
|
|
|
sdp += cam_sim_bus(xpt_path_sim(cpi->ccb_h.path));
|
1999-08-16 20:11:45 +00:00
|
|
|
cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
|
2000-04-21 19:18:06 +00:00
|
|
|
cpi->hba_misc = 0;
|
1999-05-11 05:10:06 +00:00
|
|
|
cpi->initiator_id = sdp->isp_initiator_id;
|
Add a number of interrelated CAM feature enhancements and bug fixes.
NOTE: These changes will require recompilation of any userland
applications, like cdrecord, xmcd, etc., that use the CAM passthrough
interface. A make world is recommended.
camcontrol.[c8]:
- We now support two new commands, "tags" and "negotiate".
- The tags commands allows users to view the number of tagged
openings for a device as well as a number of other related
parameters, and it allows users to set tagged openings for
a device.
- The negotiate command allows users to enable and disable
disconnection and tagged queueing, set sync rates, offsets
and bus width. Note that not all of those features are
available for all controllers. Only the adv, ahc, and ncr
drivers fully support all of the features at this point.
Some cards do not allow the setting of sync rates, offsets and
the like, and some of the drivers don't have any facilities to
do so. Some drivers, like the adw driver, only support enabling
or disabling sync negotiation, but do not support setting sync
rates.
- new description in the camcontrol man page of how to format a disk
- cleanup of the camcontrol inquiry command
- add support in the 'devlist' command for skipping unconfigured devices if
-v was not specified on the command line.
- make use of the new base_transfer_speed in the path inquiry CCB.
- fix CCB bzero cases
cam_xpt.c, cam_sim.[ch], cam_ccb.h:
- new flags on many CCB function codes to designate whether they're
non-immediate, use a user-supplied CCB, and can only be passed from
userland programs via the xpt device. Use these flags in the transport
layer and pass driver to categorize CCBs.
- new flag in the transport layer device matching code for device nodes
that indicates whether a device is unconfigured
- bump the CAM version from 0x10 to 0x11
- Change the CAM ioctls to use the version as their group code, so we can
force users to recompile code even when the CCB size doesn't change.
- add + fill in a new value in the path inquiry CCB, base_transfer_speed.
Remove a corresponding field from the cam_sim structure, and add code to
every SIM to set this field to the proper value.
- Fix the set transfer settings code in the transport layer.
scsi_cd.c:
- make some variables volatile instead of just casting them in various
places
- fix a race condition in the changer code
- attach unless we get a "logical unit not supported" error. This should
fix all of the cases where people have devices that return weird errors
when they don't have media in the drive.
scsi_da.c:
- attach unless we get a "logical unit not supported" error
scsi_pass.c:
- for immediate CCBs, just malloc a CCB to send the user request in. This
gets rid of the 'held' count problem in camcontrol tags.
scsi_pass.h:
- change the CAM ioctls to use the CAM version as their group code.
adv driver:
- Allow changing the sync rate and offset separately.
adw driver
- Allow changing the sync rate and offset separately.
aha driver:
- Don't return CAM_REQ_CMP for SET_TRAN_SETTINGS CCBs.
ahc driver:
- Allow setting offset and sync rate separately
bt driver:
- Don't return CAM_REQ_CMP for SET_TRAN_SETTINGS CCBs.
NCR driver:
- Fix the ultra/ultra 2 negotiation bug
- allow setting both the sync rate and offset separately
Other HBA drivers:
- Put code in to set the base_transfer_speed field for
XPT_GET_TRAN_SETTINGS CCBs.
Reviewed by: gibbs, mjacob (isp), imp (aha)
1999-05-06 20:16:39 +00:00
|
|
|
cpi->base_transfer_speed = 3300;
|
2006-12-18 23:50:30 +00:00
|
|
|
#ifdef CAM_NEW_TRAN_CODE
|
2001-07-04 18:54:29 +00:00
|
|
|
cpi->transport = XPORT_SPI;
|
2006-12-18 23:50:30 +00:00
|
|
|
cpi->transport_version = 2;
|
|
|
|
#endif
|
1998-09-15 08:42:56 +00:00
|
|
|
}
|
2006-12-18 23:50:30 +00:00
|
|
|
#ifdef CAM_NEW_TRAN_CODE
|
2001-07-04 18:54:29 +00:00
|
|
|
cpi->protocol = PROTO_SCSI;
|
|
|
|
cpi->protocol_version = SCSI_REV_2;
|
2006-12-18 23:50:30 +00:00
|
|
|
#endif
|
1998-09-15 08:42:56 +00:00
|
|
|
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
|
|
|
|
strncpy(cpi->hba_vid, "Qlogic", HBA_IDLEN);
|
|
|
|
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
|
|
|
|
cpi->unit_number = cam_sim_unit(sim);
|
|
|
|
cpi->ccb_h.status = CAM_REQ_CMP;
|
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
ccb->ccb_h.status = CAM_REQ_INVALID;
|
|
|
|
xpt_done(ccb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1998-12-05 01:31:21 +00:00
|
|
|
|
|
|
|
#define ISPDDB (CAM_DEBUG_INFO|CAM_DEBUG_TRACE|CAM_DEBUG_CDB)
|
2006-11-14 08:45:48 +00:00
|
|
|
|
1998-12-05 01:31:21 +00:00
|
|
|
void
|
1998-12-28 19:22:27 +00:00
|
|
|
isp_done(struct ccb_scsiio *sccb)
|
1998-12-05 01:31:21 +00:00
|
|
|
{
|
2006-04-21 18:30:01 +00:00
|
|
|
ispsoftc_t *isp = XS_ISP(sccb);
|
1998-12-05 01:31:21 +00:00
|
|
|
|
|
|
|
if (XS_NOERR(sccb))
|
|
|
|
XS_SETERR(sccb, CAM_REQ_CMP);
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
|
1998-12-05 01:31:21 +00:00
|
|
|
if ((sccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP &&
|
|
|
|
(sccb->scsi_status != SCSI_STATUS_OK)) {
|
|
|
|
sccb->ccb_h.status &= ~CAM_STATUS_MASK;
|
2000-01-04 03:45:49 +00:00
|
|
|
if ((sccb->scsi_status == SCSI_STATUS_CHECK_COND) &&
|
|
|
|
(sccb->ccb_h.status & CAM_AUTOSNS_VALID) == 0) {
|
|
|
|
sccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
|
|
|
|
} else {
|
|
|
|
sccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
|
|
|
|
}
|
1998-12-05 01:31:21 +00:00
|
|
|
}
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
|
1999-08-16 20:11:45 +00:00
|
|
|
sccb->ccb_h.status &= ~CAM_SIM_QUEUED;
|
1998-12-05 01:31:21 +00:00
|
|
|
if ((sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
2006-11-14 08:45:48 +00:00
|
|
|
isp_prt(isp, ISP_LOGDEBUG0,
|
|
|
|
"target %d lun %d CAM status 0x%x SCSI status 0x%x",
|
|
|
|
XS_TGT(sccb), XS_LUN(sccb), sccb->ccb_h.status,
|
|
|
|
sccb->scsi_status);
|
1998-12-05 01:31:21 +00:00
|
|
|
if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
|
|
|
|
sccb->ccb_h.status |= CAM_DEV_QFRZN;
|
1999-08-16 20:11:45 +00:00
|
|
|
xpt_freeze_devq(sccb->ccb_h.path, 1);
|
1998-12-05 01:31:21 +00:00
|
|
|
}
|
|
|
|
}
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
|
|
|
|
if ((CAM_DEBUGGED(sccb->ccb_h.path, ISPDDB)) &&
|
1998-12-05 01:31:21 +00:00
|
|
|
(sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
2006-12-05 07:50:23 +00:00
|
|
|
xpt_print(sccb->ccb_h.path,
|
|
|
|
"cam completion status 0x%x\n", sccb->ccb_h.status);
|
1998-12-05 01:31:21 +00:00
|
|
|
}
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
|
|
|
|
XS_CMD_S_DONE(sccb);
|
|
|
|
if (XS_CMD_WDOG_P(sccb) == 0) {
|
2006-11-14 08:45:48 +00:00
|
|
|
untimeout(isp_watchdog, sccb, sccb->ccb_h.timeout_ch);
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
if (XS_CMD_GRACE_P(sccb)) {
|
2000-08-01 06:31:44 +00:00
|
|
|
isp_prt(isp, ISP_LOGDEBUG2,
|
|
|
|
"finished command on borrowed time");
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
}
|
|
|
|
XS_CMD_S_CLEAR(sccb);
|
2007-05-05 20:17:23 +00:00
|
|
|
isp_free_pcmd(isp, (union ccb *) sccb);
|
2000-12-29 19:06:32 +00:00
|
|
|
xpt_done((union ccb *) sccb);
|
Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.
Rearchitect command watchdog timeouts-
First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).
Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).
If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.
If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
|
|
|
}
|
1998-12-05 01:31:21 +00:00
|
|
|
}
|
|
|
|
|
1999-01-30 07:29:00 +00:00
|
|
|
int
|
2006-04-21 18:30:01 +00:00
|
|
|
isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
|
1999-01-30 07:29:00 +00:00
|
|
|
{
|
1999-05-11 05:10:06 +00:00
|
|
|
int bus, rv = 0;
|
2006-11-02 03:21:32 +00:00
|
|
|
static const char prom[] =
|
|
|
|
"PortID 0x%06x handle 0x%x role %s %s\n"
|
2006-11-14 08:45:48 +00:00
|
|
|
" WWNN 0x%08x%08x WWPN 0x%08x%08x";
|
2006-11-02 03:21:32 +00:00
|
|
|
static const char prom2[] =
|
|
|
|
"PortID 0x%06x handle 0x%x role %s %s tgt %u\n"
|
2006-11-14 08:45:48 +00:00
|
|
|
" WWNN 0x%08x%08x WWPN 0x%08x%08x";
|
|
|
|
char *msg = NULL;
|
2006-11-02 03:21:32 +00:00
|
|
|
target_id_t tgt;
|
|
|
|
fcportdb_t *lp;
|
|
|
|
struct cam_path *tmppath;
|
|
|
|
|
1999-01-30 07:29:00 +00:00
|
|
|
switch (cmd) {
|
|
|
|
case ISPASYNC_NEW_TGT_PARAMS:
|
1999-08-16 20:11:45 +00:00
|
|
|
{
|
2006-12-18 23:50:30 +00:00
|
|
|
#ifdef CAM_NEW_TRAN_CODE
|
2001-07-04 18:54:29 +00:00
|
|
|
struct ccb_trans_settings_scsi *scsi;
|
|
|
|
struct ccb_trans_settings_spi *spi;
|
2006-12-18 23:50:30 +00:00
|
|
|
#endif
|
1999-08-16 20:11:45 +00:00
|
|
|
int flags, tgt;
|
|
|
|
sdparam *sdp = isp->isp_param;
|
2001-07-04 18:54:29 +00:00
|
|
|
struct ccb_trans_settings cts;
|
1999-08-16 20:11:45 +00:00
|
|
|
|
2006-05-22 06:49:49 +00:00
|
|
|
memset(&cts, 0, sizeof (struct ccb_trans_settings));
|
2001-07-04 18:54:29 +00:00
|
|
|
|
1999-08-16 20:11:45 +00:00
|
|
|
tgt = *((int *)arg);
|
|
|
|
bus = (tgt >> 16) & 0xffff;
|
|
|
|
tgt &= 0xffff;
|
|
|
|
sdp += bus;
|
|
|
|
if (xpt_create_path(&tmppath, NULL,
|
|
|
|
cam_sim_path(bus? isp->isp_sim2 : isp->isp_sim),
|
|
|
|
tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
2000-12-05 07:39:54 +00:00
|
|
|
isp_prt(isp, ISP_LOGWARN,
|
|
|
|
"isp_async cannot make temp path for %d.%d",
|
|
|
|
tgt, bus);
|
1999-08-16 20:11:45 +00:00
|
|
|
rv = -1;
|
|
|
|
break;
|
|
|
|
}
|
2001-07-30 01:00:21 +00:00
|
|
|
flags = sdp->isp_devparam[tgt].actv_flags;
|
2006-12-18 23:50:30 +00:00
|
|
|
#ifdef CAM_NEW_TRAN_CODE
|
2001-07-04 18:54:29 +00:00
|
|
|
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
|
|
|
cts.protocol = PROTO_SCSI;
|
|
|
|
cts.transport = XPORT_SPI;
|
|
|
|
|
|
|
|
scsi = &cts.proto_specific.scsi;
|
|
|
|
spi = &cts.xport_specific.spi;
|
|
|
|
|
|
|
|
if (flags & DPARM_TQING) {
|
|
|
|
scsi->valid |= CTS_SCSI_VALID_TQ;
|
|
|
|
scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
|
|
|
|
}
|
|
|
|
|
1999-08-16 20:11:45 +00:00
|
|
|
if (flags & DPARM_DISC) {
|
2001-07-04 18:54:29 +00:00
|
|
|
spi->valid |= CTS_SPI_VALID_DISC;
|
|
|
|
spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
|
|
|
|
}
|
|
|
|
spi->flags |= CTS_SPI_VALID_BUS_WIDTH;
|
|
|
|
if (flags & DPARM_WIDE) {
|
|
|
|
spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
|
|
|
|
} else {
|
|
|
|
spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
|
|
|
|
}
|
|
|
|
if (flags & DPARM_SYNC) {
|
|
|
|
spi->valid |= CTS_SPI_VALID_SYNC_RATE;
|
|
|
|
spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
|
2001-07-30 01:00:21 +00:00
|
|
|
spi->sync_period = sdp->isp_devparam[tgt].actv_period;
|
|
|
|
spi->sync_offset = sdp->isp_devparam[tgt].actv_offset;
|
2001-07-04 18:54:29 +00:00
|
|
|
}
|
2006-12-18 23:50:30 +00:00
|
|
|
#else
|
|
|
|
cts.flags = CCB_TRANS_CURRENT_SETTINGS;
|
|
|
|
cts.valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
|
|
|
|
if (flags & DPARM_DISC) {
|
|
|
|
cts.flags |= CCB_TRANS_DISC_ENB;
|
|
|
|
}
|
|
|
|
if (flags & DPARM_TQING) {
|
|
|
|
cts.flags |= CCB_TRANS_TAG_ENB;
|
|
|
|
}
|
|
|
|
cts.valid |= CCB_TRANS_BUS_WIDTH_VALID;
|
|
|
|
cts.bus_width = (flags & DPARM_WIDE)?
|
|
|
|
MSG_EXT_WDTR_BUS_8_BIT : MSG_EXT_WDTR_BUS_16_BIT;
|
|
|
|
cts.sync_period = sdp->isp_devparam[tgt].actv_period;
|
|
|
|
cts.sync_offset = sdp->isp_devparam[tgt].actv_offset;
|
|
|
|
if (flags & DPARM_SYNC) {
|
|
|
|
cts.valid |=
|
|
|
|
CCB_TRANS_SYNC_RATE_VALID |
|
|
|
|
CCB_TRANS_SYNC_OFFSET_VALID;
|
|
|
|
}
|
|
|
|
#endif
|
2000-08-01 06:31:44 +00:00
|
|
|
isp_prt(isp, ISP_LOGDEBUG2,
|
|
|
|
"NEW_TGT_PARAMS bus %d tgt %d period %x offset %x flags %x",
|
2001-07-30 01:00:21 +00:00
|
|
|
bus, tgt, sdp->isp_devparam[tgt].actv_period,
|
|
|
|
sdp->isp_devparam[tgt].actv_offset, flags);
|
2001-07-04 18:54:29 +00:00
|
|
|
xpt_setup_ccb(&cts.ccb_h, tmppath, 1);
|
|
|
|
xpt_async(AC_TRANSFER_NEG, tmppath, &cts);
|
1999-08-16 20:11:45 +00:00
|
|
|
xpt_free_path(tmppath);
|
1999-01-30 07:29:00 +00:00
|
|
|
break;
|
1999-08-16 20:11:45 +00:00
|
|
|
}
|
1999-03-17 05:04:39 +00:00
|
|
|
case ISPASYNC_BUS_RESET:
|
1999-05-11 05:10:06 +00:00
|
|
|
bus = *((int *)arg);
|
2000-08-01 06:31:44 +00:00
|
|
|
isp_prt(isp, ISP_LOGINFO, "SCSI bus reset on bus %d detected",
|
|
|
|
bus);
|
1999-05-11 05:10:06 +00:00
|
|
|
if (bus > 0 && isp->isp_path2) {
|
|
|
|
xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
|
|
|
|
} else if (isp->isp_path) {
|
1999-03-17 05:04:39 +00:00
|
|
|
xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
|
|
|
|
}
|
|
|
|
break;
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
case ISPASYNC_LIP:
|
2006-11-14 08:45:48 +00:00
|
|
|
if (msg == NULL) {
|
|
|
|
msg = "LIP Received";
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
}
|
2006-11-14 08:45:48 +00:00
|
|
|
/* FALLTHROUGH */
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
case ISPASYNC_LOOP_RESET:
|
2006-11-14 08:45:48 +00:00
|
|
|
if (msg == NULL) {
|
|
|
|
msg = "LOOP Reset";
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
}
|
2006-11-14 08:45:48 +00:00
|
|
|
/* FALLTHROUGH */
|
1999-03-17 05:04:39 +00:00
|
|
|
case ISPASYNC_LOOP_DOWN:
|
2006-11-14 08:45:48 +00:00
|
|
|
if (msg == NULL) {
|
|
|
|
msg = "LOOP Down";
|
|
|
|
}
|
1999-03-17 05:04:39 +00:00
|
|
|
if (isp->isp_path) {
|
2006-11-14 08:45:48 +00:00
|
|
|
isp_freeze_loopdown(isp, msg);
|
1999-03-17 05:04:39 +00:00
|
|
|
}
|
2006-11-14 08:45:48 +00:00
|
|
|
if (isp->isp_osinfo.ldt_running == 0) {
|
|
|
|
isp->isp_osinfo.ldt_running = 1;
|
2007-05-05 20:17:23 +00:00
|
|
|
callout_reset(&isp->isp_osinfo.ldt,
|
|
|
|
isp->isp_osinfo.loop_down_limit * hz, isp_ldt, isp);
|
2006-11-14 08:45:48 +00:00
|
|
|
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
|
|
|
|
"starting Loop Down Timer");
|
|
|
|
}
|
|
|
|
isp_prt(isp, ISP_LOGINFO, msg);
|
1999-03-17 05:04:39 +00:00
|
|
|
break;
|
|
|
|
case ISPASYNC_LOOP_UP:
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
/*
|
|
|
|
* Now we just note that Loop has come up. We don't
|
|
|
|
* actually do anything because we're waiting for a
|
|
|
|
* Change Notify before activating the FC cleanup
|
|
|
|
* thread to look at the state of the loop again.
|
|
|
|
*/
|
2000-08-01 06:31:44 +00:00
|
|
|
isp_prt(isp, ISP_LOGINFO, "Loop UP");
|
1999-03-17 05:04:39 +00:00
|
|
|
break;
|
2006-11-02 03:21:32 +00:00
|
|
|
case ISPASYNC_DEV_ARRIVED:
|
|
|
|
lp = arg;
|
2006-11-14 08:45:48 +00:00
|
|
|
lp->reserved = 0;
|
|
|
|
if ((isp->isp_role & ISP_ROLE_INITIATOR) &&
|
|
|
|
(lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT))) {
|
|
|
|
int dbidx = lp - FCPARAM(isp)->portdb;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_FC_TARG; i++) {
|
|
|
|
if (i >= FL_ID && i <= SNS_ID) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (FCPARAM(isp)->isp_ini_map[i] == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i < MAX_FC_TARG) {
|
|
|
|
FCPARAM(isp)->isp_ini_map[i] = dbidx + 1;
|
|
|
|
lp->ini_map_idx = i + 1;
|
|
|
|
} else {
|
|
|
|
isp_prt(isp, ISP_LOGWARN, "out of target ids");
|
|
|
|
isp_dump_portdb(isp);
|
|
|
|
}
|
|
|
|
}
|
2006-11-02 03:21:32 +00:00
|
|
|
if (lp->ini_map_idx) {
|
|
|
|
tgt = lp->ini_map_idx - 1;
|
|
|
|
isp_prt(isp, ISP_LOGCONFIG, prom2,
|
|
|
|
lp->portid, lp->handle,
|
2006-11-14 08:45:48 +00:00
|
|
|
roles[lp->roles], "arrived at", tgt,
|
2006-11-02 03:21:32 +00:00
|
|
|
(uint32_t) (lp->node_wwn >> 32),
|
|
|
|
(uint32_t) lp->node_wwn,
|
|
|
|
(uint32_t) (lp->port_wwn >> 32),
|
|
|
|
(uint32_t) lp->port_wwn);
|
2006-11-14 08:45:48 +00:00
|
|
|
isp_make_here(isp, tgt);
|
2006-11-02 03:21:32 +00:00
|
|
|
} else {
|
|
|
|
isp_prt(isp, ISP_LOGCONFIG, prom,
|
|
|
|
lp->portid, lp->handle,
|
2006-11-14 08:45:48 +00:00
|
|
|
roles[lp->roles], "arrived",
|
2006-11-02 03:21:32 +00:00
|
|
|
(uint32_t) (lp->node_wwn >> 32),
|
|
|
|
(uint32_t) lp->node_wwn,
|
|
|
|
(uint32_t) (lp->port_wwn >> 32),
|
|
|
|
(uint32_t) lp->port_wwn);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISPASYNC_DEV_CHANGED:
|
|
|
|
lp = arg;
|
2006-11-14 08:45:48 +00:00
|
|
|
if (isp_change_is_bad) {
|
|
|
|
lp->state = FC_PORTDB_STATE_NIL;
|
|
|
|
if (lp->ini_map_idx) {
|
|
|
|
tgt = lp->ini_map_idx - 1;
|
|
|
|
FCPARAM(isp)->isp_ini_map[tgt] = 0;
|
|
|
|
lp->ini_map_idx = 0;
|
|
|
|
isp_prt(isp, ISP_LOGCONFIG, prom3,
|
|
|
|
lp->portid, tgt, "change is bad");
|
|
|
|
isp_make_gone(isp, tgt);
|
|
|
|
} else {
|
|
|
|
isp_prt(isp, ISP_LOGCONFIG, prom,
|
|
|
|
lp->portid, lp->handle,
|
|
|
|
roles[lp->roles],
|
|
|
|
"changed and departed",
|
|
|
|
(uint32_t) (lp->node_wwn >> 32),
|
|
|
|
(uint32_t) lp->node_wwn,
|
|
|
|
(uint32_t) (lp->port_wwn >> 32),
|
|
|
|
(uint32_t) lp->port_wwn);
|
|
|
|
}
|
2006-11-02 03:21:32 +00:00
|
|
|
} else {
|
2006-11-14 08:45:48 +00:00
|
|
|
lp->portid = lp->new_portid;
|
|
|
|
lp->roles = lp->new_roles;
|
|
|
|
if (lp->ini_map_idx) {
|
|
|
|
int t = lp->ini_map_idx - 1;
|
|
|
|
FCPARAM(isp)->isp_ini_map[t] =
|
|
|
|
(lp - FCPARAM(isp)->portdb) + 1;
|
|
|
|
tgt = lp->ini_map_idx - 1;
|
|
|
|
isp_prt(isp, ISP_LOGCONFIG, prom2,
|
|
|
|
lp->portid, lp->handle,
|
|
|
|
roles[lp->roles], "changed at", tgt,
|
|
|
|
(uint32_t) (lp->node_wwn >> 32),
|
|
|
|
(uint32_t) lp->node_wwn,
|
|
|
|
(uint32_t) (lp->port_wwn >> 32),
|
|
|
|
(uint32_t) lp->port_wwn);
|
|
|
|
} else {
|
|
|
|
isp_prt(isp, ISP_LOGCONFIG, prom,
|
|
|
|
lp->portid, lp->handle,
|
|
|
|
roles[lp->roles], "changed",
|
|
|
|
(uint32_t) (lp->node_wwn >> 32),
|
|
|
|
(uint32_t) lp->node_wwn,
|
|
|
|
(uint32_t) (lp->port_wwn >> 32),
|
|
|
|
(uint32_t) lp->port_wwn);
|
|
|
|
}
|
2006-11-02 03:21:32 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISPASYNC_DEV_STAYED:
|
|
|
|
lp = arg;
|
|
|
|
if (lp->ini_map_idx) {
|
|
|
|
tgt = lp->ini_map_idx - 1;
|
|
|
|
isp_prt(isp, ISP_LOGCONFIG, prom2,
|
|
|
|
lp->portid, lp->handle,
|
2006-11-14 08:45:48 +00:00
|
|
|
roles[lp->roles], "stayed at", tgt,
|
2006-11-02 03:21:32 +00:00
|
|
|
(uint32_t) (lp->node_wwn >> 32),
|
|
|
|
(uint32_t) lp->node_wwn,
|
|
|
|
(uint32_t) (lp->port_wwn >> 32),
|
|
|
|
(uint32_t) lp->port_wwn);
|
|
|
|
} else {
|
|
|
|
isp_prt(isp, ISP_LOGCONFIG, prom,
|
|
|
|
lp->portid, lp->handle,
|
2006-11-14 08:45:48 +00:00
|
|
|
roles[lp->roles], "stayed",
|
2006-11-02 03:21:32 +00:00
|
|
|
(uint32_t) (lp->node_wwn >> 32),
|
|
|
|
(uint32_t) lp->node_wwn,
|
|
|
|
(uint32_t) (lp->port_wwn >> 32),
|
|
|
|
(uint32_t) lp->port_wwn);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISPASYNC_DEV_GONE:
|
|
|
|
lp = arg;
|
2006-11-14 08:45:48 +00:00
|
|
|
/*
|
|
|
|
* If this has a virtual target and we haven't marked it
|
|
|
|
* that we're going to have isp_gdt tell the OS it's gone,
|
|
|
|
* set the isp_gdt timer running on it.
|
|
|
|
*
|
|
|
|
* If it isn't marked that isp_gdt is going to get rid of it,
|
|
|
|
* announce that it's gone.
|
|
|
|
*/
|
|
|
|
if (lp->ini_map_idx && lp->reserved == 0) {
|
|
|
|
lp->reserved = 1;
|
|
|
|
lp->new_reserved = isp->isp_osinfo.gone_device_time;
|
|
|
|
lp->state = FC_PORTDB_STATE_ZOMBIE;
|
|
|
|
if (isp->isp_osinfo.gdt_running == 0) {
|
|
|
|
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
|
|
|
|
"starting Gone Device Timer");
|
|
|
|
isp->isp_osinfo.gdt_running = 1;
|
2007-05-05 20:17:23 +00:00
|
|
|
callout_reset(&isp->isp_osinfo.gdt, hz,
|
|
|
|
isp_gdt, isp);
|
2006-11-14 08:45:48 +00:00
|
|
|
}
|
2006-11-02 03:21:32 +00:00
|
|
|
tgt = lp->ini_map_idx - 1;
|
|
|
|
isp_prt(isp, ISP_LOGCONFIG, prom2,
|
|
|
|
lp->portid, lp->handle,
|
2006-11-14 08:45:48 +00:00
|
|
|
roles[lp->roles], "gone zombie at", tgt,
|
2006-11-02 03:21:32 +00:00
|
|
|
(uint32_t) (lp->node_wwn >> 32),
|
|
|
|
(uint32_t) lp->node_wwn,
|
|
|
|
(uint32_t) (lp->port_wwn >> 32),
|
|
|
|
(uint32_t) lp->port_wwn);
|
2006-11-14 08:45:48 +00:00
|
|
|
} else if (lp->reserved == 0) {
|
2006-11-02 03:21:32 +00:00
|
|
|
isp_prt(isp, ISP_LOGCONFIG, prom,
|
|
|
|
lp->portid, lp->handle,
|
2006-11-14 08:45:48 +00:00
|
|
|
roles[lp->roles], "departed",
|
|
|
|
(uint32_t) (lp->node_wwn >> 32),
|
2006-11-02 03:21:32 +00:00
|
|
|
(uint32_t) lp->node_wwn,
|
2006-11-14 08:45:48 +00:00
|
|
|
(uint32_t) (lp->port_wwn >> 32),
|
2006-11-02 03:21:32 +00:00
|
|
|
(uint32_t) lp->port_wwn);
|
|
|
|
}
|
1999-03-17 05:04:39 +00:00
|
|
|
break;
|
|
|
|
case ISPASYNC_CHANGE_NOTIFY:
|
2006-11-02 03:21:32 +00:00
|
|
|
{
|
|
|
|
char *msg;
|
2001-07-25 04:23:52 +00:00
|
|
|
if (arg == ISPASYNC_CHANGE_PDB) {
|
2006-11-02 03:21:32 +00:00
|
|
|
msg = "Port Database Changed";
|
2001-07-25 04:23:52 +00:00
|
|
|
} else if (arg == ISPASYNC_CHANGE_SNS) {
|
2006-11-02 03:21:32 +00:00
|
|
|
msg = "Name Server Database Changed";
|
|
|
|
} else {
|
|
|
|
msg = "Other Change Notify";
|
2001-01-09 02:47:15 +00:00
|
|
|
}
|
2006-11-14 08:45:48 +00:00
|
|
|
/*
|
|
|
|
* If the loop down timer is running, cancel it.
|
|
|
|
*/
|
|
|
|
if (isp->isp_osinfo.ldt_running) {
|
|
|
|
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
|
|
|
|
"Stopping Loop Down Timer");
|
|
|
|
isp->isp_osinfo.ldt_running = 0;
|
2007-05-05 20:17:23 +00:00
|
|
|
callout_stop(&isp->isp_osinfo.ldt);
|
2006-11-14 08:45:48 +00:00
|
|
|
}
|
2006-11-02 03:21:32 +00:00
|
|
|
isp_prt(isp, ISP_LOGINFO, msg);
|
|
|
|
isp_freeze_loopdown(isp, msg);
|
2007-05-05 20:17:23 +00:00
|
|
|
wakeup(ISP_KT_WCHAN(isp));
|
1999-03-17 05:04:39 +00:00
|
|
|
break;
|
|
|
|
}
|
2000-01-03 23:55:30 +00:00
|
|
|
#ifdef ISP_TARGET_MODE
|
2006-01-23 06:23:37 +00:00
|
|
|
case ISPASYNC_TARGET_NOTIFY:
|
2000-01-03 23:55:30 +00:00
|
|
|
{
|
2006-01-23 06:23:37 +00:00
|
|
|
tmd_notify_t *nt = arg;
|
I don't know what I was thinking- if I have two separate busses on on
SIM (as is true for the 1280 and the 12160), then I have to have separate
flags && status for *both* busses. *Whap*.
Implement condition variables for coordination with some target mode
events. It's nice to use these and not panic in obscure little places
in the kernel like 'propagate_priority' just because we went to sleep
holding a mutex, or some other absurd thing.
Remove some bogus ISP_UNLOCK calls. *Whap*.
No longer require that somebody do a lun enable on the wildcard device
to enable target mode. They are, in fact, orthogonal. A wildcard open
is a statement that somebody upstream is willing to accept commands which
are otherwise unrouteable. Now, for QLogic regular SCSI target mode, this
won't matter for a damn because we'll never see ATIOs for luns we haven't
enabled (are listening for, if you will). But for SCCLUN fibre channel
SCSI, we get all kinds of ATIOs. We can either reflect them back here
with minimal info (which is isp_target.c:isp_endcmd() is for), or the
wildcard device (nominally targbh) can handle them.
Do further checking against firmware attributes to see whether we can,
in fact, support target mode in Fibre Channel. For now, require SCCLUN
f/w to supoprt FC target mode.
This is an awful lot of change, but target mode *still* isn't quite right.
MFC after: 4 weeks
2001-09-04 21:53:12 +00:00
|
|
|
isp_prt(isp, ISP_LOGALL,
|
2006-01-23 06:23:37 +00:00
|
|
|
"target notify code 0x%x", nt->nt_ncode);
|
2000-01-03 23:55:30 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISPASYNC_TARGET_ACTION:
|
|
|
|
switch (((isphdr_t *)arg)->rqs_entry_type) {
|
|
|
|
default:
|
2000-12-05 07:39:54 +00:00
|
|
|
isp_prt(isp, ISP_LOGWARN,
|
|
|
|
"event 0x%x for unhandled target action",
|
|
|
|
((isphdr_t *)arg)->rqs_entry_type);
|
2000-01-03 23:55:30 +00:00
|
|
|
break;
|
2002-06-16 05:08:02 +00:00
|
|
|
case RQSTYPE_NOTIFY:
|
|
|
|
if (IS_SCSI(isp)) {
|
|
|
|
rv = isp_handle_platform_notify_scsi(isp,
|
|
|
|
(in_entry_t *) arg);
|
|
|
|
} else {
|
|
|
|
rv = isp_handle_platform_notify_fc(isp,
|
|
|
|
(in_fcentry_t *) arg);
|
|
|
|
}
|
|
|
|
break;
|
2000-01-03 23:55:30 +00:00
|
|
|
case RQSTYPE_ATIO:
|
|
|
|
rv = isp_handle_platform_atio(isp, (at_entry_t *) arg);
|
|
|
|
break;
|
|
|
|
case RQSTYPE_ATIO2:
|
|
|
|
rv = isp_handle_platform_atio2(isp, (at2_entry_t *)arg);
|
|
|
|
break;
|
2006-05-22 07:07:30 +00:00
|
|
|
case RQSTYPE_CTIO3:
|
2000-01-03 23:55:30 +00:00
|
|
|
case RQSTYPE_CTIO2:
|
|
|
|
case RQSTYPE_CTIO:
|
|
|
|
rv = isp_handle_platform_ctio(isp, arg);
|
|
|
|
break;
|
|
|
|
case RQSTYPE_ENABLE_LUN:
|
|
|
|
case RQSTYPE_MODIFY_LUN:
|
2004-02-08 19:17:56 +00:00
|
|
|
isp_ledone(isp, (lun_entry_t *) arg);
|
2000-01-03 23:55:30 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
1999-07-02 23:12:58 +00:00
|
|
|
#endif
|
2001-07-04 18:54:29 +00:00
|
|
|
case ISPASYNC_FW_CRASH:
|
|
|
|
{
|
2006-02-15 00:31:48 +00:00
|
|
|
uint16_t mbox1, mbox6;
|
2001-07-04 18:54:29 +00:00
|
|
|
mbox1 = ISP_READ(isp, OUTMAILBOX1);
|
|
|
|
if (IS_DUALBUS(isp)) {
|
|
|
|
mbox6 = ISP_READ(isp, OUTMAILBOX6);
|
|
|
|
} else {
|
|
|
|
mbox6 = 0;
|
|
|
|
}
|
|
|
|
isp_prt(isp, ISP_LOGERR,
|
2002-06-16 05:08:02 +00:00
|
|
|
"Internal Firmware Error on bus %d @ RISC Address 0x%x",
|
2001-07-04 18:54:29 +00:00
|
|
|
mbox6, mbox1);
|
2002-08-17 17:23:15 +00:00
|
|
|
#ifdef ISP_FW_CRASH_DUMP
|
2007-05-05 20:17:23 +00:00
|
|
|
mbox1 = isp->isp_osinfo.mbox_sleep_ok;
|
|
|
|
isp->isp_osinfo.mbox_sleep_ok = 0;
|
2002-08-17 17:23:15 +00:00
|
|
|
if (IS_FC(isp)) {
|
|
|
|
FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
|
|
|
|
FCPARAM(isp)->isp_loopstate = LOOP_NIL;
|
|
|
|
isp_freeze_loopdown(isp, "f/w crash");
|
|
|
|
isp_fw_dump(isp);
|
|
|
|
}
|
2001-07-04 18:54:29 +00:00
|
|
|
isp_reinit(isp);
|
2007-05-05 20:17:23 +00:00
|
|
|
isp->isp_osinfo.mbox_sleep_ok = mbox1;
|
|
|
|
#else
|
|
|
|
mbox1 = isp->isp_osinfo.mbox_sleep_ok;
|
|
|
|
isp->isp_osinfo.mbox_sleep_ok = 0;
|
|
|
|
isp_reinit(isp);
|
|
|
|
isp->isp_osinfo.mbox_sleep_ok = mbox1;
|
2002-08-17 17:23:15 +00:00
|
|
|
#endif
|
2007-05-05 20:17:23 +00:00
|
|
|
isp_async(isp, ISPASYNC_FW_RESTARTED, NULL);
|
2001-07-04 18:54:29 +00:00
|
|
|
break;
|
|
|
|
}
|
2001-08-16 17:25:41 +00:00
|
|
|
case ISPASYNC_UNHANDLED_RESPONSE:
|
|
|
|
break;
|
1999-01-30 07:29:00 +00:00
|
|
|
default:
|
2000-08-01 06:31:44 +00:00
|
|
|
isp_prt(isp, ISP_LOGERR, "unknown isp_async event %d", cmd);
|
1999-01-30 07:29:00 +00:00
|
|
|
break;
|
|
|
|
}
|
1999-07-02 23:12:58 +00:00
|
|
|
return (rv);
|
1999-01-30 07:29:00 +00:00
|
|
|
}
|
1998-12-28 19:22:27 +00:00
|
|
|
|
1999-07-02 23:12:58 +00:00
|
|
|
|
1998-12-28 19:22:27 +00:00
|
|
|
/*
|
|
|
|
* Locks are held before coming here.
|
|
|
|
*/
|
|
|
|
void
|
2006-04-21 18:30:01 +00:00
|
|
|
isp_uninit(ispsoftc_t *isp)
|
1998-12-28 19:22:27 +00:00
|
|
|
{
|
2006-11-02 03:21:32 +00:00
|
|
|
if (IS_24XX(isp)) {
|
|
|
|
ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET);
|
|
|
|
} else {
|
|
|
|
ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
|
|
|
|
}
|
|
|
|
ISP_DISABLE_INTS(isp);
|
1998-12-28 19:22:27 +00:00
|
|
|
}
|
2000-08-01 06:31:44 +00:00
|
|
|
|
|
|
|
void
|
2006-04-21 18:30:01 +00:00
|
|
|
isp_prt(ispsoftc_t *isp, int level, const char *fmt, ...)
|
2000-08-01 06:31:44 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
if (level != ISP_LOGALL && (level & isp->isp_dblev) == 0) {
|
|
|
|
return;
|
|
|
|
}
|
2001-03-01 02:14:54 +00:00
|
|
|
printf("%s: ", device_get_nameunit(isp->isp_dev));
|
2000-08-01 06:31:44 +00:00
|
|
|
va_start(ap, fmt);
|
|
|
|
vprintf(fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
printf("\n");
|
|
|
|
}
|
2006-11-14 08:45:48 +00:00
|
|
|
|
|
|
|
uint64_t
|
|
|
|
isp_nanotime_sub(struct timespec *b, struct timespec *a)
|
|
|
|
{
|
|
|
|
uint64_t elapsed;
|
|
|
|
struct timespec x = *b;
|
|
|
|
timespecsub(&x, a);
|
|
|
|
elapsed = GET_NANOSEC(&x);
|
|
|
|
if (elapsed == 0)
|
|
|
|
elapsed++;
|
|
|
|
return (elapsed);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
isp_mbox_acquire(ispsoftc_t *isp)
|
|
|
|
{
|
|
|
|
if (isp->isp_osinfo.mboxbsy) {
|
|
|
|
return (1);
|
|
|
|
} else {
|
|
|
|
isp->isp_osinfo.mboxcmd_done = 0;
|
|
|
|
isp->isp_osinfo.mboxbsy = 1;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
isp_mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp)
|
|
|
|
{
|
2006-12-17 16:59:19 +00:00
|
|
|
unsigned int usecs = mbp->timeout;
|
|
|
|
unsigned int max, olim, ilim;
|
2006-11-14 08:45:48 +00:00
|
|
|
|
|
|
|
if (usecs == 0) {
|
|
|
|
usecs = MBCMD_DEFAULT_TIMEOUT;
|
|
|
|
}
|
2006-12-17 16:59:19 +00:00
|
|
|
max = isp->isp_mbxwrk0 + 1;
|
|
|
|
|
2006-11-14 08:45:48 +00:00
|
|
|
if (isp->isp_osinfo.mbox_sleep_ok) {
|
2006-12-17 16:59:19 +00:00
|
|
|
unsigned int ms = (usecs + 999) / 1000;
|
|
|
|
|
2006-11-14 08:45:48 +00:00
|
|
|
isp->isp_osinfo.mbox_sleep_ok = 0;
|
|
|
|
isp->isp_osinfo.mbox_sleeping = 1;
|
2006-12-17 16:59:19 +00:00
|
|
|
for (olim = 0; olim < max; olim++) {
|
2007-05-05 20:17:23 +00:00
|
|
|
#if __FreeBSD_version < 700037
|
2006-12-17 16:59:19 +00:00
|
|
|
tsleep(&isp->isp_mbxworkp, PRIBIO, "ispmbx_sleep",
|
|
|
|
isp_mstohz(ms));
|
2006-11-14 08:45:48 +00:00
|
|
|
#else
|
2007-05-05 20:17:23 +00:00
|
|
|
msleep(&isp->isp_mbxworkp, &isp->isp_osinfo.lock,
|
|
|
|
PRIBIO, "ispmbx_sleep", isp_mstohz(ms));
|
2006-11-14 08:45:48 +00:00
|
|
|
#endif
|
|
|
|
if (isp->isp_osinfo.mboxcmd_done) {
|
|
|
|
break;
|
|
|
|
}
|
2006-12-17 16:59:19 +00:00
|
|
|
}
|
|
|
|
isp->isp_osinfo.mbox_sleep_ok = 1;
|
|
|
|
isp->isp_osinfo.mbox_sleeping = 0;
|
|
|
|
} else {
|
|
|
|
for (olim = 0; olim < max; olim++) {
|
|
|
|
for (ilim = 0; ilim < usecs; ilim += 100) {
|
|
|
|
uint32_t isr;
|
|
|
|
uint16_t sema, mbox;
|
2006-11-14 08:45:48 +00:00
|
|
|
if (isp->isp_osinfo.mboxcmd_done) {
|
|
|
|
break;
|
|
|
|
}
|
2006-12-17 16:59:19 +00:00
|
|
|
if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
|
|
|
|
isp_intr(isp, isr, sema, mbox);
|
|
|
|
if (isp->isp_osinfo.mboxcmd_done) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
USEC_DELAY(100);
|
|
|
|
}
|
|
|
|
if (isp->isp_osinfo.mboxcmd_done) {
|
|
|
|
break;
|
2006-11-14 08:45:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isp->isp_osinfo.mboxcmd_done == 0) {
|
|
|
|
isp_prt(isp, ISP_LOGWARN,
|
2007-02-23 05:51:57 +00:00
|
|
|
"%s Mailbox Command (0x%x) Timeout (%uus)",
|
2006-11-14 08:45:48 +00:00
|
|
|
isp->isp_osinfo.mbox_sleep_ok? "Interrupting" : "Polled",
|
2007-02-23 05:51:57 +00:00
|
|
|
isp->isp_lastmbxcmd, usecs);
|
2006-11-14 08:45:48 +00:00
|
|
|
mbp->param[0] = MBOX_TIMEOUT;
|
|
|
|
isp->isp_osinfo.mboxcmd_done = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
isp_mbox_notify_done(ispsoftc_t *isp)
|
|
|
|
{
|
|
|
|
if (isp->isp_osinfo.mbox_sleeping) {
|
|
|
|
wakeup(&isp->isp_mbxworkp);
|
|
|
|
}
|
|
|
|
isp->isp_osinfo.mboxcmd_done = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
isp_mbox_release(ispsoftc_t *isp)
|
|
|
|
{
|
|
|
|
isp->isp_osinfo.mboxbsy = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
isp_mstohz(int ms)
|
|
|
|
{
|
2006-12-17 16:59:19 +00:00
|
|
|
int hz;
|
2006-11-14 08:45:48 +00:00
|
|
|
struct timeval t;
|
|
|
|
t.tv_sec = ms / 1000;
|
|
|
|
t.tv_usec = (ms % 1000) * 1000;
|
2006-12-17 16:59:19 +00:00
|
|
|
hz = tvtohz(&t);
|
|
|
|
if (hz < 0) {
|
|
|
|
hz = 0x7fffffff;
|
|
|
|
}
|
|
|
|
if (hz == 0) {
|
|
|
|
hz = 1;
|
2006-11-14 08:45:48 +00:00
|
|
|
}
|
2006-12-17 16:59:19 +00:00
|
|
|
return (hz);
|
2006-11-14 08:45:48 +00:00
|
|
|
}
|
2007-05-05 20:17:23 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
isp_platform_intr(void *arg)
|
|
|
|
{
|
|
|
|
ispsoftc_t *isp = arg;
|
|
|
|
uint32_t isr;
|
|
|
|
uint16_t sema, mbox;
|
|
|
|
|
|
|
|
ISP_LOCK(isp);
|
|
|
|
isp->isp_intcnt++;
|
|
|
|
if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) {
|
|
|
|
isp->isp_intbogus++;
|
|
|
|
} else {
|
|
|
|
isp_intr(isp, isr, sema, mbox);
|
|
|
|
}
|
|
|
|
ISP_UNLOCK(isp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
isp_common_dmateardown(ispsoftc_t *isp, struct ccb_scsiio *csio, uint32_t hdl)
|
|
|
|
{
|
|
|
|
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
|
|
|
|
bus_dmamap_sync(isp->isp_osinfo.dmat,
|
|
|
|
PISP_PCMD(csio)->dmap, BUS_DMASYNC_POSTREAD);
|
|
|
|
} else {
|
|
|
|
bus_dmamap_sync(isp->isp_osinfo.dmat,
|
|
|
|
PISP_PCMD(csio)->dmap, BUS_DMASYNC_POSTWRITE);
|
|
|
|
}
|
|
|
|
bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap);
|
|
|
|
}
|